summaryrefslogtreecommitdiff
path: root/spectro/i1d3.c
diff options
context:
space:
mode:
Diffstat (limited to 'spectro/i1d3.c')
-rw-r--r--spectro/i1d3.c732
1 files changed, 508 insertions, 224 deletions
diff --git a/spectro/i1d3.c b/spectro/i1d3.c
index 53b2f0c..cf0fc08 100644
--- a/spectro/i1d3.c
+++ b/spectro/i1d3.c
@@ -7,7 +7,7 @@
* Author: Graeme W. Gill
* Date: 28/7/2011
*
- * Copyright 2006 - 2013, Graeme W. Gill
+ * Copyright 2006 - 2014, Graeme W. Gill
* All rights reserved.
*
* (Based on huey.c)
@@ -58,6 +58,14 @@
#undef PLOT_SPECTRA /* Plot the sensor senitivity spectra */
#undef SAVE_SPECTRA /* Save the sensor senitivity spectra to "sensors.cmf" */
#undef PLOT_REFRESH /* Plot data used to determine refresh rate */
+#undef PLOT_UPDELAY /* Plot data used to determine display update delay */
+
+#undef DEBUG_TWEAKS /* Allow environment variable tweaks to int time etc. */
+/* I1D3_MIN_REF_QUANT_TIME in seconds. Default 0.05 */
+/* I1D3_MIN_INT_TIME in seconds. Default 0.4 for refresh displays */
+
+#define I1D3_MEAS_TIMEOUT 40.0 /* Longest reading timeout in seconds */
+ /* Typically 20.0 is the maximum needed. */
static inst_code i1d3_interp_code(inst *pp, int ec);
static inst_code i1d3_check_unlock(i1d3 *p);
@@ -145,7 +153,7 @@ static char *inst_desc(i1Disp3CC cc) {
case i1d3_rd_sensor:
return "ReadAnalogSensor";
case i1d3_get_diff:
- return "GetDiffuserPositio";
+ return "GetDiffuserPosition";
case i1d3_lockchal:
return "GetLockChallenge";
case i1d3_lockresp:
@@ -186,8 +194,14 @@ i1d3_command(
if (cmd == 0x00)
send[1] = (cc & 0xff); /* Minor command */
- if (!nd) a1logd(p->log, 4, "i1d3_command: Sending cmd '%s' args '%s'\n",
- inst_desc(cc), icoms_tohex(send, 8));
+ if (!nd) {
+ if (cc == i1d3_lockresp)
+ a1logd(p->log, 4, "i1d3_command: Sending cmd '%s' args '%s'\n",
+ inst_desc(cc), icoms_tohex(send, 64));
+ else
+ a1logd(p->log, 4, "i1d3_command: Sending cmd '%s' args '%s'\n",
+ inst_desc(cc), icoms_tohex(send, 8));
+ }
if (p->icom->port_type(p->icom) == icomt_hid) {
se = p->icom->hid_write(p->icom, send, 64, &wbytes, to);
@@ -196,6 +210,12 @@ i1d3_command(
}
if (se != 0) {
if (!nd) a1logd(p->log, 1, "i1d3_command: Command send failed with ICOM err 0x%x\n",se);
+ /* Flush any response */
+ if (ishid) {
+ p->icom->hid_read(p->icom, recv, 64, &rbytes, to);
+ } else {
+ p->icom->usb_read(p->icom, NULL, 0x81, recv, 64, &rbytes, to);
+ }
amutex_unlock(p->lock);
return i1d3_interp_code((inst *)p, I1D3_COMS_FAIL);
}
@@ -213,7 +233,7 @@ i1d3_command(
p->icom->hid_read(p->icom, recv, 64, &rbytes, to);
} else {
p->icom->usb_read(p->icom, NULL, 0x81, recv, 64, &rbytes, to);
- }
+ }
amutex_unlock(p->lock);
return rv;
}
@@ -228,6 +248,12 @@ i1d3_command(
}
if (se != 0) {
if (!nd) a1logd(p->log, 1, "i1d3_command: response read failed with ICOM err 0x%x\n",se);
+ /* Flush any extra response, in case responses are out of sync */
+ if (ishid) {
+ p->icom->hid_read(p->icom, recv, 64, &rbytes, 0.2);
+ } else {
+ p->icom->usb_read(p->icom, NULL, 0x81, recv, 64, &rbytes, 0.2);
+ }
amutex_unlock(p->lock);
return i1d3_interp_code((inst *)p, I1D3_COMS_FAIL);
}
@@ -237,12 +263,13 @@ i1d3_command(
}
/* The first byte returned seems to be a command result error code. */
- /* The second byte is usually the command code being echo'd back, but not always. */
if (rv == inst_ok && recv[0] != 0x00) {
if (!nd) a1logd(p->log, 1, "i1d3_command: status byte != 00 = 0x%x\n",recv[0]);
rv = i1d3_interp_code((inst *)p, I1D3_BAD_RET_STAT);
}
+ /* The second byte is usually the command code being echo'd back, but not always. */
+ /* ie., get i1d3_get_diff returns the status instead. */
if (rv == inst_ok) {
if (cc != i1d3_get_diff) {
if (recv[1] != cmd) {
@@ -250,31 +277,35 @@ i1d3_command(
cmd,recv[1]);
rv = i1d3_interp_code((inst *)p, I1D3_BAD_RET_CMD);
}
+ } else { /* i1d3_get_diff as special case */
+ int i;
+ for (i = 2; i < 64; i++) {
+ if (recv[i] != 0x00) {
+ if (!nd) a1logd(p->log, 1, "i1d3_command: i1d3_get_diff not zero filled\n");
+ rv = i1d3_interp_code((inst *)p, I1D3_BAD_RET_CMD);
+ break;
+ }
+ }
}
}
- if (!nd) a1logd(p->log, 4, "i1d3_command: got '%s' ICOM err 0x%x\n",icoms_tohex(recv, 14),ua);
-
- amutex_unlock(p->lock);
- return rv;
-}
-
-/* Read a packet and time out or throw it away */
-static inst_code
-i1d3_dummy_read(
- i1d3 *p /* i1d3 object */
-) {
- unsigned char buf[64];
- int rbytes; /* bytes read from ep */
- int se, rv = inst_ok;
- int ishid = p->icom->port_type(p->icom) == icomt_hid;
+ if (!nd) {
+ if (cc == i1d3_lockchal)
+ a1logd(p->log, 4, "i1d3_command: got '%s' ICOM err 0x%x\n",icoms_tohex(recv, 64),ua);
+ else
+ a1logd(p->log, 4, "i1d3_command: got '%s' ICOM err 0x%x\n",icoms_tohex(recv, 14),ua);
+ }
- if (ishid) {
- se = p->icom->hid_read(p->icom, buf, 64, &rbytes, 0.1);
- } else {
- se = p->icom->usb_read(p->icom, NULL, 0x81, buf, 64, &rbytes, 0.1);
- }
+ if (rv != inst_ok) {
+ /* Flush any extra response, in case responses are out of sync */
+ if (ishid) {
+ p->icom->hid_read(p->icom, recv, 64, &rbytes, 0.2);
+ } else {
+ p->icom->usb_read(p->icom, NULL, 0x81, recv, 64, &rbytes, 0.2);
+ }
+ }
+ amutex_unlock(p->lock);
return rv;
}
@@ -534,19 +565,26 @@ i1d3_unlock(
{ "i1Display3 ", { 0xcaa62b2c, 0x30815b61 }, i1d3_disppro, i1d3_oem },
{ "i1Display3 ", { 0xa9119479, 0x5b168761 }, i1d3_disppro, i1d3_nec_ssp },
{ "i1Display3 ", { 0x160eb6ae, 0x14440e70 }, i1d3_disppro, i1d3_quato_sh3 },
+ { "i1Display3 ", { 0x291e41d7, 0x51937bdd }, i1d3_disppro, i1d3_hp_dreamc },
{ NULL }
};
inst_code ev;
- int ix;
+ int ix, nix;
a1logd(p->log, 2, "i1d3_unlock: called\n");
+ /* Count the keys */
+ for (nix = 0;;nix++) {
+ if (codes[nix].pname == NULL)
+ break;
+ }
+
/* Until we give up */
for (ix = 0;;ix++) {
/* If we've run out of unlock keys */
if (codes[ix].pname == NULL) {
- a1logd(p->log, 1, "i1d3: Unknown lock code. Please contact ArgyllCMS for help\n");
+ a1logw(p->log, "i1d3: Unknown lock code. Please contact ArgyllCMS for help\n");
return i1d3_interp_code((inst *)p, I1D3_UNKNOWN_UNLOCK);
}
@@ -559,6 +597,7 @@ i1d3_unlock(
// a1logd(p->log, 3, "i1d3_unlock: Trying unlock key 0x%08x 0x%08x\n",
// codes[ix].key[0], codes[ix].key[1]);
+ a1logd(p->log, 3, "i1d3_unlock: Trying unlock key %d/%d\n", ix+1, nix);
p->dtype = codes[ix].dtype;
p->stype = codes[ix].stype;
@@ -734,7 +773,7 @@ i1d3_freq_measure(
todev[23] = 0; /* Unknown parameter, always 0 */
- if ((ev = i1d3_command(p, i1d3_measure1, todev, fromdev, 20.0, 0)) != inst_ok)
+ if ((ev = i1d3_command(p, i1d3_measure1, todev, fromdev, I1D3_MEAS_TIMEOUT, 0)) != inst_ok)
return ev;
rgb[0] = (double)buf2uint(fromdev + 2);
@@ -771,7 +810,7 @@ i1d3_period_measure(
todev[7] = (unsigned char)mask;
todev[8] = 0; /* Unknown parameter, always 0 */
- if ((ev = i1d3_command(p, i1d3_measure2, todev, fromdev, 20.0, 0)) != inst_ok)
+ if ((ev = i1d3_command(p, i1d3_measure2, todev, fromdev, I1D3_MEAS_TIMEOUT, 0)) != inst_ok)
return ev;
rgb[0] = (double)buf2uint(fromdev + 2);
@@ -911,6 +950,7 @@ i1d3_imp_measure_refresh(
int npeaks = 0; /* Number of peaks */
double pval; /* Period value */
int isdeb;
+ int isth;
if (prefrate != NULL)
*prefrate = 0.0;
@@ -922,14 +962,17 @@ i1d3_imp_measure_refresh(
return inst_internal_error;
}
- /* Turn debug off so that it doesn't intefere with measurement timing */
+ /* Turn debug and thread off so that they doesn't intefere with measurement timing */
isdeb = p->log->debug;
p->icom->log->debug = 0;
+ isth = p->th_en;
+ p->th_en = 0;
/* Do some measurement and throw them away, to make sure the code is in cache. */
for (i = 0; i < 5; i++) {
if ((ev = i1d3_freq_measure(p, &inttimeh, samp[i].rgb)) != inst_ok) {
p->log->debug = isdeb;
+ p->th_en = isth;
return ev;
}
}
@@ -945,6 +988,7 @@ i1d3_imp_measure_refresh(
if ((ev = i1d3_freq_measure(p, &inttime1, samp[0].rgb)) != inst_ok) {
p->log->debug = isdeb;
+ p->th_en = isth;
return ev;
}
@@ -952,6 +996,7 @@ i1d3_imp_measure_refresh(
if ((ev = i1d3_freq_measure(p, &inttime2, samp[0].rgb)) != inst_ok) {
p->log->debug = isdeb;
+ p->th_en = isth;
return ev;
}
@@ -977,10 +1022,10 @@ i1d3_imp_measure_refresh(
if ((ev = i1d3_freq_measure(p, &samp[i].itime, samp[i].rgb)) != inst_ok) {
p->log->debug = isdeb;
+ p->th_en = isth;
return ev;
}
cutime = (usec_time() - sutime) / 1000000.0;
-// ~~999
samp[i].sec = 0.5 * (putime + cutime); /* Mean of before and after stamp */
//samp[i].sec *= 85.0/20.0; /* Test 20 Hz */
//samp[i].sec *= 85.0/100.0; /* Test 100 Hz */
@@ -988,7 +1033,9 @@ i1d3_imp_measure_refresh(
if (cutime > NFMXTIME)
break;
}
+ /* Restore debug & thread */
p->log->debug = isdeb;
+ p->th_en = isth;
nfsamps = i;
if (nfsamps < 100) {
@@ -1354,6 +1401,7 @@ i1d3_imp_measure_refresh(
} else {
int mul;
double refrate;
+ double pval;
pval = avg/ano;
pval /= 1000.0; /* Convert to seconds */
@@ -1365,10 +1413,25 @@ i1d3_imp_measure_refresh(
/* Error against my 85Hz CRT - GWG */
// a1logd(p->log, 1, "Refresh rate error = %.4f%%\n",100.0 * fabs(refrate - 85.0)/(85.0));
- /* Scale to just above 20 Hz */
- mul = floor((1.0/20) / pval);
- if (mul > 1)
+ /* Scale to just above 20 Hz, but make it multiple of 2 or 4 */
+#ifdef DEBUG_TWEAKS
+ {
+ double quanttime = 1.0/20.0;
+ char *cp;
+ if ((cp = getenv("I1D3_MIN_REF_QUANT_TIME")) != NULL)
+ quanttime = atof(cp);
+ mul = (int)floor(quanttime / pval);
+ }
+#else
+ mul = (int)floor((1.0/20.0) / pval);
+#endif
+ if (mul > 1) {
+ if (mul >= 8)
+ mul = (mul + 3) & ~3; /* Round up to mult of 4 */
+ else
+ mul = (mul + 1) & ~1; /* Round up to mult of 2 */
pval *= mul;
+ }
a1logd(p->log, 1, "Refresh rate = %f Hz, quantizing to %f msec\n",refrate,pval);
a1logv(p->log, 1, "Refresh rate = %f Hz, quantizing to %f msec\n",refrate,pval);
@@ -1411,6 +1474,8 @@ i1d3_measure_set_refresh(
/* - - - - - - - - - - - - - - - - - - - - - - */
+#ifdef NEVER /* No longer used - use general measurement instead */
+
/* Take an ambient measurement and return the cooked reading */
/* The cooked reading is the frequency of the L2V */
static inst_code
@@ -1451,11 +1516,11 @@ i1d3_take_amb_measurement(
return inst_ok;
}
-
+#endif
/* - - - - - - - - - - - - - - - - - - - - - - */
-/* Take an display measurement and return the cooked reading */
+/* Take a general measurement and return the cooked reading */
/* The cooked reading is the frequency of the L2V */
static inst_code
i1d3_take_emis_measurement(
@@ -1464,26 +1529,22 @@ i1d3_take_emis_measurement(
double *rgb /* Return the cooked emsissive RGB values */
) {
int i, k;
- int pos;
inst_code ev;
double rmeas[3] = { -1.0, -1.0, -1.0 }; /* raw measurement */
int edgec[3] = {2,2,2}; /* Measurement edge count for each channel (not counting start edge) */
int mask = 0x7; /* Period measure mask */
int msecstart = msec_time(); /* Debug */
double rgb2[3] = { 0.0, 0.0, 0.0 }; /* Trial measurement RGB values */
+ int isth;
if (p->inited == 0)
return i1d3_interp_code((inst *)p, I1D3_NOT_INITED);
a1logd(p->log,3,"\ntake_emis_measurement called\n");
- /* Check that the ambient filter is not in place */
- if ((ev = i1d3_get_diffpos(p, &pos, 0)) != inst_ok)
- return ev;
-
- if (pos != 0)
- return i1d3_interp_code((inst *)p, I1D3_SPOS_EMIS);
-
+ /* Suspend thread so that it doesn't intefere with measurement timing */
+ isth = p->th_en;
+ p->th_en = 0;
/* If we should take a frequency measurement first */
if (mode == i1d3_adaptive || mode == i1d3_frequency) {
@@ -1492,8 +1553,10 @@ i1d3_take_emis_measurement(
a1logd(p->log,3,"Doing fixed period frequency measurement over %f secs\n",p->inttime);
/* Take a frequency measurement over a fixed period */
- if ((ev = i1d3_freq_measure(p, &p->inttime, rmeas)) != inst_ok)
+ if ((ev = i1d3_freq_measure(p, &p->inttime, rmeas)) != inst_ok) {
+ p->th_en = isth;
return ev;
+ }
/* Convert to frequency (assume raw meas is both edges count over integration time) */
for (i = 0; i < 3; i++) {
@@ -1555,8 +1618,10 @@ i1d3_take_emis_measurement(
a1logd(p->log,3,"Doing 1st period pre-measurement mask 0x%x, edgec %d %d %d\n",mask2,edgec[0],edgec[1],edgec[2]);
/* Take an initial period pre-measurement over 2 edges */
- if ((ev = i1d3_period_measure(p, edgec, mask2, rmeas2)) != inst_ok)
+ if ((ev = i1d3_period_measure(p, edgec, mask2, rmeas2)) != inst_ok) {
+ p->th_en = isth;
return ev;
+ }
a1logd(p->log,3,"Got %f %f %f raw %f %f %f Hz\n",rmeas2[0],rmeas2[1],rmeas2[2],
0.5 * edgec[0] * p->clk_freq/rmeas2[0],
@@ -1627,8 +1692,10 @@ i1d3_take_emis_measurement(
a1logd(p->log,3,"Doing 2nd initial period measurement mask 0x%x, edgec %d %d %d\n",mask2,edgec[0],edgec[1],edgec[2]);
/* Take a 2nd initial period measurement */
- if ((ev = i1d3_period_measure(p, edgec, mask3, rmeas2)) != inst_ok)
+ if ((ev = i1d3_period_measure(p, edgec, mask3, rmeas2)) != inst_ok) {
+ p->th_en = isth;
return ev;
+ }
a1logd(p->log,3,"Got %f %f %f raw %f %f %f Hz\n",rmeas2[0],rmeas2[1],rmeas2[2],
0.5 * edgec[0] * p->clk_freq/rmeas2[0],
@@ -1659,7 +1726,7 @@ i1d3_take_emis_measurement(
continue;
/* Compute number of edges needed for a clock count */
- /* of p->inttime (0.2 secs) */
+ /* of p->inttime (0.2/0.4 secs) */
nedgec = edgec[i] * p->inttime * p->clk_freq/rmeas[i];
/* If we will get less than 200 edges, raise the target integration */
@@ -1780,8 +1847,10 @@ i1d3_take_emis_measurement(
a1logd(p->log,3,"Doing freq re-measure inttime %f\n",tinttime);
/* Take a frequency measurement over a fixed period */
- if ((ev = i1d3_freq_measure(p, &tinttime, rmeas)) != inst_ok)
+ if ((ev = i1d3_freq_measure(p, &tinttime, rmeas)) != inst_ok) {
+ p->th_en = isth;
return ev;
+ }
/* Convert raw measurement to frequency */
for (i = 0; i < 3; i++) {
@@ -1799,8 +1868,10 @@ i1d3_take_emis_measurement(
a1logd(p->log,3,"Doing period re-measure mask 0x%x, edgec %d %d %d\n",mask,edgec[0],edgec[1],edgec[2]);
/* Measure again with desired precision, taking up to 0.4/0.8 secs */
- if ((ev = i1d3_period_measure(p, edgec, mask, rmeas)) != inst_ok)
+ if ((ev = i1d3_period_measure(p, edgec, mask, rmeas)) != inst_ok) {
+ p->th_en = isth;
return ev;
+ }
for (i = 0; i < 3; i++) {
double tt;
@@ -1820,6 +1891,7 @@ i1d3_take_emis_measurement(
}
}
}
+ p->th_en = isth;
a1logd(p->log,3,"Took %d msec to measure\n", msec_time() - msecstart);
@@ -1843,27 +1915,35 @@ i1d3_take_XYZ_measurement(
i1d3 *p, /* Object */
double XYZ[3] /* Return the XYZ values */
) {
+ int pos;
inst_code ev;
if (IMODETST(p->mode, inst_mode_emis_ambient)) {
- if ((ev = i1d3_take_amb_measurement(p, XYZ)) != inst_ok)
+
+ /* Check that the ambient filter is in place */
+ if ((ev = i1d3_get_diffpos(p, &pos, 0)) != inst_ok)
+ return ev;
+
+ if (pos != 1)
+ return i1d3_interp_code((inst *)p, I1D3_SPOS_EMIS);
+
+ /* Best type of reading, including refresh support */
+ if ((ev = i1d3_take_emis_measurement(p, i1d3_adaptive, XYZ)) != inst_ok)
return ev;
/* Multiply by ambient calibration matrix */
- icmMulBy3x3(XYZ, p->ambi_cal, XYZ);
- icmScale3(XYZ, XYZ, 1/3.141592654); /* Convert from Lux to cd/m^2 */
+ icmMulBy3x3(XYZ, p->ambi_cal, XYZ); /* Values in Lux */
} else {
- /* Constant fast speed, poor accuracy for black */
-// if ((ev = i1d3_take_emis_measurement(p, i1d3_frequency, XYZ)) != inst_ok)
-// return ev;
-
- /* Most accurate ? */
-// if ((ev = i1d3_take_emis_measurement(p, i1d3_period, XYZ)) != inst_ok)
-// return ev;
+ /* Check that the ambient filter is not in place */
+ if ((ev = i1d3_get_diffpos(p, &pos, 0)) != inst_ok)
+ return ev;
+
+ if (pos != 0)
+ return i1d3_interp_code((inst *)p, I1D3_SPOS_EMIS);
- /* Best combination */
+ /* Best type of reading, including refresh support */
if ((ev = i1d3_take_emis_measurement(p, i1d3_adaptive, XYZ)) != inst_ok)
return ev;
@@ -1892,6 +1972,9 @@ static inst_code i1d3_decode_intEE(
strncpy(p->serial_no, (char *)buf + 0x10, 20);
p->serial_no[20] = '\000';
+ strncpy(p->vers_no, (char *)buf + 0x2C, 10);
+ p->serial_no[10] = '\000';
+
/* Read the black level offset */
for (i = 0; i < 3; i++) {
t1 = buf2uint(buf + 0x0004 + 4 * i);
@@ -1915,16 +1998,22 @@ static inst_code i1d3_decode_extEE(
unsigned int chsum, rchsum;
xspect tmp;
- for (chsum = 0, i = 4; i < 6042; i++)
- chsum += buf[i];
+ rchsum = buf2short(buf + 2);
- chsum &= 0xffff; /* 16 bit sum */
+ /* For the "A-01" revsions the checksum is from 4 to 0x179a */
+ /* The "A-02" seems to have abandoned reliable checksums ?? */
+ for (chsum = 0, i = 4; i < 0x179a; i++) {
+ chsum += buf[i];
+ }
- rchsum = buf2short(buf + 2);
+ chsum &= 0xffff;
if (rchsum != chsum) {
- a1logd(p->log, 3, "i1d3_decode_extEE: checksum failed\n");
- return i1d3_interp_code((inst *)p, I1D3_BAD_EX_CHSUM);
+ a1logd(p->log, 3, "i1d3_decode_extEE: checksum failed, is 0x%x, should be 0x%x\n",chsum,rchsum);
+ if (strcmp(p->vers_no, "A-01") == 0)
+ return i1d3_interp_code((inst *)p, I1D3_BAD_EX_CHSUM);
+
+ /* Else ignore checksum error */
}
/* Read 3 x sensor spectral sensitivits */
@@ -2116,6 +2205,108 @@ i1d3_comp_calmat(
return inst_ok;
}
+/* Preset the calibration to a spectral sample type. */
+/* ccmat[][] is set to unity */
+static inst_code
+i1d3_set_speccal(
+ i1d3 *p,
+ xspect *samples, /* Array of nsamp spectral samples, or RGBcmfs for MIbLSr */
+ int nsamp /* Number of samples */
+) {
+ int i;
+
+ /* Save a the spectral samples to the current state */
+ if (p->samples != NULL)
+ free(p->samples);
+ p->nsamp = 0;
+ if ((p->samples = (xspect *)calloc(sizeof(xspect), nsamp)) == NULL) {
+ a1loge(p->log, inst_internal_error, "i1d3_set_speccal: malloc failed\n");
+ return inst_internal_error;
+ }
+ for (i = 0; i < nsamp; i++ )
+ p->samples[i] = samples[i]; /* Struct copy */
+ p->nsamp = nsamp;
+
+ icmSetUnity3x3(p->ccmat); /* No matrix */
+
+ return inst_ok;
+}
+
+
+/* Preset the calibration to a matrix. The spectral type is set to none */
+static inst_code
+i1d3_set_matcal(i1d3 *p, double mtx[3][3]) {
+ if (mtx == NULL)
+ icmSetUnity3x3(p->ccmat);
+ else {
+ if (p->cbid == 0) {
+ a1loge(p->log, 1, "i1d3: can't set col_cor_mat over non-base display type\n");
+ return inst_wrong_setup;
+ }
+ icmCpy3x3(p->ccmat, mtx);
+ }
+ return inst_ok;
+}
+
+
+/* Set the calibration to the currently preset type */
+static inst_code
+i1d3_set_cal(i1d3 *p) {
+ inst_code ev = inst_ok;
+
+ if (p->samples != NULL && p->nsamp > 0) {
+
+ /* Create matrix for specified samples */
+ if ((ev = i1d3_comp_calmat(p, p->emis_cal, p->obType, p->custObserver,
+ p->sens, p->samples, p->nsamp)) != inst_ok) {
+ a1logd(p->log, 1, "i1d3_set_cal: comp_calmat ccss failed with rv = 0x%x\n",ev);
+ return ev;
+ }
+ /* Use MIbLSr for ambient */
+ if ((ev = i1d3_comp_calmat(p, p->ambi_cal, p->obType, p->custObserver,
+ p->ambi, p->ambi, 3)) != inst_ok)
+ return ev;
+
+ icmSetUnity3x3(p->ccmat); /* to be sure to be sure... */
+
+ } else { /* Assume matrix */
+
+ /* Create the default MIbLSr calibration matrix */
+ if ((ev = i1d3_comp_calmat(p, p->emis_cal, p->obType, p->custObserver,
+ p->sens, p->sens, 3)) != inst_ok) {
+ a1logd(p->log, 1, "i1d3_set_disp_type: comp_calmat dflt failed with rv = 0x%x\n",ev);
+ return ev;
+ }
+ /* Use MIbLSr for ambient */
+ if ((ev = i1d3_comp_calmat(p, p->ambi_cal, p->obType, p->custObserver,
+ p->ambi, p->ambi, 3)) != inst_ok)
+ return ev;
+ }
+
+ if (p->log->debug >= 4) {
+ a1logd(p->log,4,"Emissive matrix = %f %f %f\n",
+ p->emis_cal[0][0], p->emis_cal[0][1], p->emis_cal[0][2]);
+ a1logd(p->log,4," %f %f %f\n",
+ p->emis_cal[1][0], p->emis_cal[1][1], p->emis_cal[1][2]);
+ a1logd(p->log,4," %f %f %f\n\n",
+ p->emis_cal[2][0], p->emis_cal[2][1], p->emis_cal[2][2]);
+ a1logd(p->log,4,"Ambient matrix = %f %f %f\n",
+ p->ambi_cal[0][0], p->ambi_cal[0][1], p->ambi_cal[0][2]);
+ a1logd(p->log,4," %f %f %f\n",
+ p->ambi_cal[1][0], p->ambi_cal[1][1], p->ambi_cal[1][2]);
+ a1logd(p->log,4," %f %f %f\n\n",
+ p->ambi_cal[2][0], p->ambi_cal[2][1], p->ambi_cal[2][2]);
+ a1logd(p->log,4,"ccmat = %f %f %f\n",
+ p->ccmat[0][0], p->ccmat[0][1], p->ccmat[0][2]);
+ a1logd(p->log,4," %f %f %f\n",
+ p->ccmat[1][0], p->ccmat[1][1], p->ccmat[1][2]);
+ a1logd(p->log,4," %f %f %f\n\n",
+ p->ccmat[2][0], p->ccmat[2][1], p->ccmat[2][2]);
+ a1logd(p->log,4,"\n");
+ }
+
+ return inst_ok;
+}
/* ------------------------------------------------------------------------ */
@@ -2175,15 +2366,10 @@ i1d3_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
}
} else {
- a1logd(p->log, 1, "i1d3_init_coms: wrong sort of coms!\n");
- return i1d3_interp_code((inst *)p, I1D3_UNKNOWN_MODEL);
+ a1logd(p->log, 1, "i1d3_init_coms: wrong communications type for device!\n");
+ return inst_coms_fail;
}
-#if defined(__APPLE__)
- /* We seem to have to clear any pending messages for OS X HID */
- i1d3_dummy_read(p);
-#endif
-
/* Check instrument is responding */
if ((ev = i1d3_check_status(p,&stat)) != inst_ok) {
a1logd(p->log, 1, "i1d3_init_coms: failed with rv = 0x%x\n",ev);
@@ -2214,7 +2400,7 @@ static void dump_bytes(a1log *log, char *pfx, unsigned char *buf, int len) {
bp += sprintf(bp,".");
}
bp += sprintf(bp,"\n");
- a1logd(log,0,oline);
+ a1logd(log,0, "%s", oline);
bp = oline;
}
}
@@ -2230,20 +2416,25 @@ int i1d3_diff_thread(void *pp) {
for (nfailed = 0; nfailed < 5;) {
int pos;
- rv = i1d3_get_diffpos(p, &pos, 1);
- if (p->th_term) {
- p->th_termed = 1;
- break;
- }
- if (rv != inst_ok) {
- nfailed++;
- a1logd(p->log,3,"Diffuser thread failed with 0x%x\n",rv);
- continue;
- }
- if (pos != p->dpos) {
- p->dpos = pos;
- if (p->eventcallback != NULL) {
- p->eventcallback(p->event_cntx, inst_event_mconf);
+ /* Don't get diffpos if we're doing something else that */
+ /* is timing critical */
+ if (p->th_en) {
+//a1logd(p->log,3,"Diffuser thread loop debug = %d\n",p->log->debug);
+ rv = i1d3_get_diffpos(p, &pos, p->log->debug < 8 ? 1 : 0);
+ if (p->th_term) {
+ p->th_termed = 1;
+ break;
+ }
+ if (rv != inst_ok) {
+ nfailed++;
+ a1logd(p->log,3,"Diffuser thread failed with 0x%x\n",rv);
+ continue;
+ }
+ if (pos != p->dpos) {
+ p->dpos = pos;
+ if (p->eventcallback != NULL) {
+ p->eventcallback(p->event_cntx, inst_event_mconf);
+ }
}
}
msec_sleep(100);
@@ -2262,7 +2453,7 @@ i1d3_init_inst(inst *pp) {
int i, stat;
unsigned char buf[8192];
- a1logd(p->log, 2, "i1d3_init_inst: called\n");
+ a1logd(p->log, 2, "i1d3_init_inst: called, debug = %d\n",p->log->debug);
p->rrset = 0;
@@ -2329,9 +2520,11 @@ i1d3_init_inst(inst *pp) {
return ev;
/* Set known constants */
- p->clk_freq = 12e6; /* 12 Mhz */
- p->dinttime = 0.2; /* 0.2 second integration time default */
- p->inttime = p->dinttime; /* Start in non-refresh mode */
+ p->clk_freq = 12e6; /* 12 Mhz */
+ p->omininttime = 0.0; /* No override */
+ p->dinttime = 0.2; /* 0.2 second integration time default */
+ p->inttime = p->dinttime; /* Start in non-refresh mode */
+ p->mininttime = p->inttime; /* Current value */
/* Create the default calibrations */
@@ -2353,29 +2546,32 @@ i1d3_init_inst(inst *pp) {
if (p->log->debug >= 4) {
a1logd(p->log,4,"Default calibration:\n");
- a1logd(p->log,4,"Ambient matrix = %f %f %f\n",
- p->ambi_cal[0][0], p->ambi_cal[0][1], p->ambi_cal[0][2]);
- a1logd(p->log,4," %f %f %f\n",
- p->ambi_cal[1][0], p->ambi_cal[1][1], p->ambi_cal[1][2]);
- a1logd(p->log,4," %f %f %f\n\n",
- p->ambi_cal[2][0], p->ambi_cal[2][1], p->ambi_cal[2][2]);
a1logd(p->log,4,"Emissive matrix = %f %f %f\n",
p->emis_cal[0][0], p->emis_cal[0][1], p->emis_cal[0][2]);
a1logd(p->log,4," %f %f %f\n",
p->emis_cal[1][0], p->emis_cal[1][1], p->emis_cal[1][2]);
a1logd(p->log,4," %f %f %f\n",
p->emis_cal[2][0], p->emis_cal[2][1], p->emis_cal[2][2]);
+ a1logd(p->log,4,"Ambient matrix = %f %f %f\n",
+ p->ambi_cal[0][0], p->ambi_cal[0][1], p->ambi_cal[0][2]);
+ a1logd(p->log,4," %f %f %f\n",
+ p->ambi_cal[1][0], p->ambi_cal[1][1], p->ambi_cal[1][2]);
+ a1logd(p->log,4," %f %f %f\n\n",
+ p->ambi_cal[2][0], p->ambi_cal[2][1], p->ambi_cal[2][2]);
a1logd(p->log,4,"\n");
}
/* Start the diffuser monitoring thread */
+ p->th_en = 1;
if ((p->th = new_athread(i1d3_diff_thread, (void *)p)) == NULL)
- return I1D3_INT_THREADFAILED;
+ return i1d3_interp_code((inst *)p, I1D3_INT_THREADFAILED);
/* Flash the LED, just cos we can! */
if ((ev = i1d3_set_LEDs(p, i1d3_flash, 0.2, 0.05, 2)) != inst_ok)
return ev;
+ a1logd(p->log, 2, "i1d3_init_inst: done\n");
+
return ev;
}
@@ -2422,26 +2618,40 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */
} else {
/* Check for abort */
if (p->uicallback != NULL
- && (rv = p->uicallback(p->uic_cntx, inst_armed)) == inst_user_abort)
+ && (rv = p->uicallback(p->uic_cntx, inst_armed)) == inst_user_abort) {
return rv; /* Abort */
+ }
}
/* Attempt a refresh display frame rate calibration if needed */
if (p->dtype != i1d3_munkdisp && p->refrmode != 0 && p->rrset == 0) {
inst_code ev = inst_ok;
+ p->mininttime = 2.0 * p->dinttime;
+
+ if (p->omininttime != 0.0)
+ p->mininttime = p->omininttime; /* Override */
+
+#ifdef DEBUG_TWEAKS
+ {
+ char *cp;
+ if ((cp = getenv("I1D3_MIN_INT_TIME")) != NULL)
+ p->mininttime = atof(cp);
+ }
+#endif
+
if ((ev = i1d3_measure_set_refresh(p)) != inst_ok)
return ev;
/* Quantize the sample time */
if (p->refperiod > 0.0) { /* If we have a refresh period */
int n;
- n = (int)ceil(p->dinttime/p->refperiod);
- p->inttime = 2.0 * n * p->refperiod;
+ n = (int)ceil(p->mininttime/p->refperiod);
+ p->inttime = n * p->refperiod;
a1logd(p->log, 3, "i1d3: integration time quantize to %f secs\n",p->inttime);
- } else { /* We don't have a period, so simply double the default */
- p->inttime = 2.0 * p->dinttime;
+ } else { /* We don't have a period, so simply use the double default */
+ p->inttime = p->mininttime;
a1logd(p->log, 3, "i1d3: integration time integration time doubled to %f secs\n",p->inttime);
}
}
@@ -2463,6 +2673,7 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */
val->sp.spec_n = 0;
val->duration = 0.0;
+
if (user_trig)
return inst_user_trig;
@@ -2491,6 +2702,7 @@ double *ref_rate) {
if (*ref_rate == 0.0)
return inst_misread;
+
return inst_ok;
}
@@ -2502,23 +2714,19 @@ inst *pp,
double mtx[3][3]
) {
i1d3 *p = (i1d3 *)pp;
+ inst_code ev = inst_ok;
+
+ a1logd(p->log, 4, "i1d3_col_cor_mat%s\n",mtx == NULL ? " (noop)": "");
if (!p->gotcoms)
return inst_no_coms;
if (!p->inited)
return inst_no_init;
- if (mtx == NULL)
- icmSetUnity3x3(p->ccmat);
- else {
- if (p->cbid == 0) {
- a1loge(p->log, 1, "i1d3: can't set col_cor_mat over non base display type\n");
- inst_wrong_setup;
- }
- icmCpy3x3(p->ccmat, mtx);
- }
-
- return inst_ok;
+ if ((ev = i1d3_set_matcal(p, mtx)) != inst_ok)
+ return ev;
+
+ return i1d3_set_cal(p);
}
/* Use a Colorimeter Calibration Spectral Set to set the */
@@ -2533,6 +2741,8 @@ int no_sets
i1d3 *p = (i1d3 *)pp;
inst_code ev = inst_ok;
+ a1logd(p->log, 4, "i1d3_col_cal_spec_set%s\n",sets == NULL ? " (default)": "");
+
if (!p->gotcoms)
return inst_no_coms;
if (!p->inited)
@@ -2543,31 +2753,12 @@ int no_sets
return ev;
}
} else {
- /* Use given spectral samples */
- if ((ev = i1d3_comp_calmat(p, p->emis_cal, p->obType, p->custObserver, p->sens,
- sets, no_sets)) != inst_ok)
- return ev;
- /* Use MIbLSr */
- if ((ev = i1d3_comp_calmat(p, p->ambi_cal, p->obType, p->custObserver, p->ambi,
- p->ambi, 3)) != inst_ok)
- return ev;
- }
- if (p->log->debug >= 4) {
- a1logd(p->log,4,"CCSS update calibration:\n");
- a1logd(p->log,4,"Ambient matrix = %f %f %f\n",
- p->ambi_cal[0][0], p->ambi_cal[0][1], p->ambi_cal[0][2]);
- a1logd(p->log,4," %f %f %f\n",
- p->ambi_cal[1][0], p->ambi_cal[1][1], p->ambi_cal[1][2]);
- a1logd(p->log,4," %f %f %f\n\n",
- p->ambi_cal[2][0], p->ambi_cal[2][1], p->ambi_cal[2][2]);
- a1logd(p->log,4,"Emissive matrix = %f %f %f\n",
- p->emis_cal[0][0], p->emis_cal[0][1], p->emis_cal[0][2]);
- a1logd(p->log,4," %f %f %f\n",
- p->emis_cal[1][0], p->emis_cal[1][1], p->emis_cal[1][2]);
- a1logd(p->log,4," %f %f %f\n",
- p->emis_cal[2][0], p->emis_cal[2][1], p->emis_cal[2][2]);
- a1logd(p->log,4,"\n");
+ if ((ev = i1d3_set_speccal(p, sets, no_sets)) != inst_ok)
+ return ev;
+
+ ev = i1d3_set_cal(p);
}
+
return ev;
}
@@ -2638,11 +2829,24 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */
if ((*calt & inst_calt_ref_freq) && p->dtype != i1d3_munkdisp && p->refrmode != 0) {
inst_code ev = inst_ok;
- if (*calc != inst_calc_emis_white) {
- *calc = inst_calc_emis_white;
+ p->mininttime = 2.0 * p->dinttime;
+
+ if (*calc != inst_calc_emis_80pc) {
+ *calc = inst_calc_emis_80pc;
return inst_cal_setup;
}
+ if (p->omininttime != 0.0)
+ p->mininttime = p->omininttime; /* Override */
+
+#ifdef DEBUG_TWEAKS
+ {
+ char *cp;
+ if ((cp = getenv("I1D3_MIN_INT_TIME")) != NULL)
+ p->mininttime = atof(cp);
+ }
+#endif
+
/* Do refresh display rate calibration */
if ((ev = i1d3_measure_set_refresh(p)) != inst_ok)
return ev;
@@ -2650,11 +2854,11 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */
/* Quantize the sample time */
if (p->refperiod > 0.0) {
int n;
- n = (int)ceil(p->dinttime/p->refperiod);
- p->inttime = 2.0 * n * p->refperiod;
+ n = (int)ceil(p->mininttime/p->refperiod);
+ p->inttime = n * p->refperiod;
a1logd(p->log, 3, "i1d3: integration time quantize to %f secs\n",p->inttime);
} else {
- p->inttime = 2.0 * p->dinttime; /* Double default integration time */
+ p->inttime = p->mininttime; /* Double default integration time */
a1logd(p->log, 3, "i1d3: integration time integration time doubled to %f secs\n",p->inttime);
}
*calt &= ~inst_calt_ref_freq;
@@ -2665,11 +2869,11 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */
/* Measure a display update delay. It is assumed that a */
/* white to black change has been made to the displayed color, */
/* and this will measure the time it took for the update to */
-/* be noticed by the instrument, up to 0.5 seconds. */
+/* be noticed by the instrument, up to 0.6 seconds. */
/* inst_misread will be returned on failure to find a transition to black. */
-#define NDSAMPS 60
-#define DINTT 0.010
-#define NDMXTIME 0.6 /* Maximum time to take */
+#define NDSAMPS 200
+#define DINTT 0.005 /* Too short hits blanking */
+#define NDMXTIME 1.0 /* Maximum time to take */
inst_code i1d3_meas_delay(
inst *pp,
@@ -2681,21 +2885,25 @@ int *msecdelay) { /* Return the number of msec */
struct {
double sec;
double rgb[3];
+ double tot;
} samp[NDSAMPS];
int ndsamps;
double inttime = DINTT;
- double rgb[3];
+ double stot, etot, del, thr;
double etime;
int isdeb;
+ int isth;
if (usec_time() < 0.0) {
a1loge(p->log, inst_internal_error, "i1d3_meas_delay: No high resolution timers\n");
return inst_internal_error;
}
- /* Turn debug off so that it doesn't intefere with measurement timing */
+ /* Turn debug and thread off so that they doesn't intefere with measurement timing */
isdeb = p->log->debug;
p->icom->log->debug = 0;
+ isth = p->th_en;
+ p->th_en = 0;
/* Read the samples */
sutime = usec_time();
@@ -2704,71 +2912,85 @@ int *msecdelay) { /* Return the number of msec */
if ((ev = i1d3_freq_measure(p, &inttime, samp[i].rgb)) != inst_ok) {
a1logd(p->log, 1, "i1d3_meas_delay: measurement failed\n");
p->log->debug = isdeb;
+ p->th_en = isth;
return ev;
}
cutime = (usec_time() - sutime) / 1000000.0;
samp[i].sec = 0.5 * (putime + cutime); /* Mean of before and after stamp */
putime = cutime;
+ samp[i].tot = samp[i].rgb[0] + samp[i].rgb[1] + samp[i].rgb[2];
if (cutime > NDMXTIME)
break;
}
ndsamps = i;
- /* Restore debugging */
+ /* Restore debugging & thread */
p->log->debug = isdeb;
+ p->th_en = isth;
if (ndsamps == 0) {
a1logd(p->log, 1, "i1d3_meas_delay: No measurement samples returned in time\n");
return inst_internal_error;
}
-#ifdef NEVER
+#ifdef PLOT_UPDELAY
/* Plot the raw sensor values */
{
double xx[NDSAMPS];
double y1[NDSAMPS];
double y2[NDSAMPS];
double y3[NDSAMPS];
+ double y4[NDSAMPS];
for (i = 0; i < ndsamps; i++) {
xx[i] = samp[i].sec;
y1[i] = samp[i].rgb[0];
y2[i] = samp[i].rgb[1];
y3[i] = samp[i].rgb[2];
- //printf("%d: %f -> %f\n",i,samp[i].sec, samp[i].rgb[0]);
+ y4[i] = samp[i].tot;
+ //printf("%d: %f -> %f\n",i,samp[i].sec, samp[i].tot);
}
printf("Display update delay measure sensor values and time (sec)\n");
- do_plot6(xx, y1, y2, y3, NULL, NULL, NULL, ndsamps);
+ do_plot6(xx, y1, y2, y3, y4, NULL, NULL, ndsamps);
}
#endif
+ /* Over the first 100msec, locate the maximum value */
+ etime = samp[ndsamps-1].sec;
+ stot = -1e9;
+ for (i = 0; i < ndsamps; i++) {
+ if (samp[i].tot > stot)
+ stot = samp[i].tot;
+ if (samp[i].sec > 0.1)
+ break;
+ }
+
/* Over the last 100msec, locate the maximum value */
etime = samp[ndsamps-1].sec;
- for (j = 0; j < 3; j++)
- rgb[j] = 0.0;
+ etot = -1e9;
for (i = ndsamps-1; i >= 0; i--) {
- for (j = 0; j < 3; j++) {
- if (samp[i].rgb[j] > rgb[j])
- rgb[j] = samp[i].rgb[j];
- }
+ if (samp[i].tot > etot)
+ etot = samp[i].tot;
if ((etime - samp[i].sec) > 0.1)
break;
}
-// a1logd(p->log, 3, "i1d3_meas_delay: end rgb = %f %f %f stopped at %d\n", rgb[0], rgb[1], rgb[2], i);
+ del = stot - etot;
+ thr = etot + 0.2 * del; /* 20% of transition threshold */
+
+#ifdef PLOT_UPDELAY
+ a1logd(p->log, 0, "i1d3_meas_delay: start tot %f end tot %f del %f, thr %f\n", stot, etot, del, thr);
+#endif
- if (rgb[0] > 10.0 || rgb[1] > 10.0 || rgb[2] > 10.0) {
- a1logd(p->log, 1, "i1d3_meas_delay: measurement delay doesn't seem to be black\n");
+ /* Check that there has been a transition */
+ if (del < 10.0) {
+ a1logd(p->log, 1, "i1d3_meas_delay: can't detect change from white to black\n");
return inst_misread;
}
- /* Locate the time at which the values are above this */
+ /* Working from the end, locate the time at which the level was above the threshold */
for (i = ndsamps-1; i >= 0; i--) {
- for (j = 0; j < 3; j++) {
- if (samp[i].rgb[j] > (1.5 * rgb[j]))
- break;
- }
- if (j < 3)
+ if (samp[i].tot > thr)
break;
}
if (i < 0) /* Assume the update was so fast that we missed it */
@@ -2778,6 +3000,10 @@ int *msecdelay) { /* Return the number of msec */
*msecdelay = (int)(samp[i].sec * 1000.0 + 0.5);
+#ifdef PLOT_UPDELAY
+ a1logd(p->log, 0, "i1d3_meas_delay: returning %d msec\n",*msecdelay);
+#endif
+
return inst_ok;
}
#undef NDSAMPS
@@ -2819,13 +3045,27 @@ double ref_rate
int mul;
double pval;
- /* Scale to just above 20 Hz */
+ /* Scale to just above 20 Hz, but make it multiple of 2 or 4 */
pval = 1.0/ref_rate;
- mul = floor((1.0/20) / pval);
- if (mul > 1)
+#ifdef DEBUG_TWEAKS
+ {
+ double quanttime = 1.0/20.0;
+ char *cp;
+ if ((cp = getenv("I1D3_MIN_REF_QUANT_TIME")) != NULL)
+ quanttime = atof(cp);
+ mul = (int)floor(quanttime / pval);
+ }
+#else
+ mul = (int)floor((1.0/20.0) / pval);
+#endif
+ if (mul > 1) {
+ if (mul >= 8)
+ mul = (mul + 3) & ~3; /* Round up to mult of 4 */
+ else
+ mul = (mul + 1) & ~1; /* Round up to mult of 2 */
pval *= mul;
+ }
p->refperiod = pval;
-
p->refrvalid = 1;
}
p->rrset = 1;
@@ -2994,6 +3234,8 @@ i1d3_del(inst *pp) {
if (p->icom != NULL)
p->icom->del(p->icom);
inst_del_disptype_list(p->dtlist, p->ndtlist);
+ if (p->samples != NULL)
+ free(p->samples);
amutex_del(p->lock);
free(p);
}
@@ -3011,7 +3253,7 @@ inst3_capability *pcap3) {
cap1 |= inst_mode_emis_spot
| inst_mode_emis_tele
| inst_mode_emis_ambient
- | inst_mode_emis_refresh_ovd
+ | inst_mode_emis_refresh_ovd /* (allow override ccmx & ccss mode) */
| inst_mode_emis_norefresh_ovd
| inst_mode_colorimeter
;
@@ -3023,11 +3265,14 @@ inst3_capability *pcap3) {
| inst2_disptype
| inst2_ccmx
| inst2_ccss
+ | inst2_get_min_int_time
+ | inst2_set_min_int_time
;
if (p->dtype != i1d3_munkdisp) {
cap2 |= inst2_meas_disp_update;
- cap2 |= inst2_refresh_rate;
+ cap2 |= inst2_get_refresh_rate;
+ cap2 |= inst2_set_refresh_rate;
cap2 |= inst2_emis_refr_meas;
}
if (pcap1 != NULL)
@@ -3075,8 +3320,8 @@ int *conf_ix
/* Add the extra dependent and independent modes */
mval |= inst_mode_emis_refresh_ovd
- | inst_mode_emis_norefresh_ovd
- | inst_mode_colorimeter;
+ | inst_mode_emis_norefresh_ovd
+ | inst_mode_colorimeter;
if (mmodes != NULL)
*mmodes = mval;
@@ -3139,11 +3384,15 @@ inst_code i1d3_set_mode(inst *pp, inst_mode m) {
}
p->refrmode = refrmode;
+ /* default before any refresh rate calibration */
if (p->refrmode) {
p->inttime = 2.0 * p->dinttime; /* Double default integration time */
} else {
p->inttime = p->dinttime; /* Normal integration time */
}
+ if (p->omininttime != 0.0)
+ p->inttime = p->omininttime; /* Override */
+ p->mininttime = p->inttime; /* Current value */
return inst_ok;
}
@@ -3152,7 +3401,7 @@ inst_disptypesel i1d3_disptypesel[3] = {
{
inst_dtflags_default,
1,
- "n",
+ "nl",
"Non-Refresh display",
0,
0
@@ -3160,7 +3409,7 @@ inst_disptypesel i1d3_disptypesel[3] = {
{
inst_dtflags_none, /* flags */
2, /* cbid */
- "r", /* sel */
+ "rc", /* sel */
"Refresh display", /* desc */
1, /* refr */
1 /* ix */
@@ -3186,7 +3435,7 @@ int recreate /* nz to re-check for new ccmx & ccss files */
i1d3 *p = (i1d3 *)pp;
inst_code rv = inst_ok;
- if (!allconfig && p->dpos) { /* If set to Ambient */
+ if (!allconfig && p->dpos) { /* If set to Ambient, there are no display types ? */
if (pnsels != NULL)
*pnsels = 0;
@@ -3233,59 +3482,31 @@ static inst_code set_disp_type(i1d3 *p, inst_disptypesel *dentry) {
p->rrset = 0; /* This is a hint we may have swapped displays */
p->refrmode = refrmode;
-// if (p->refrmode && p->dtype == i1d3_munkdisp) {
if (p->refrmode) {
p->inttime = 2.0 * p->dinttime; /* Double integration time */
} else {
p->inttime = p->dinttime; /* Normal integration time */
}
+ if (p->omininttime != 0.0)
+ p->inttime = p->omininttime; /* Override */
+ p->mininttime = p->inttime; /* Current value */
- if (dentry->flags & inst_dtflags_ccss) {
+ if (dentry->flags & inst_dtflags_ccss) { /* Spectral sample */
- if ((ev = i1d3_comp_calmat(p, p->emis_cal, p->obType, p->custObserver,
- p->sens, dentry->sets, dentry->no_sets)) != inst_ok) {
- a1logd(p->log, 1, "i1d3_set_disp_type: comp_calmat ccss failed with rv = 0x%x\n",ev);
+ if ((ev = i1d3_set_speccal(p, dentry->sets, dentry->no_sets)) != inst_ok)
return ev;
- }
- /* Use MIbLSr for ambient */
- if ((ev = i1d3_comp_calmat(p, p->ambi_cal, p->obType, p->custObserver, p->ambi,
- p->ambi, 3)) != inst_ok)
- return ev;
-
- icmSetUnity3x3(p->ccmat);
- if (p->log->debug >= 4) {
- a1logd(p->log,4,"Display type set CCSS:\n");
- a1logd(p->log,4,"Emissive matrix = %f %f %f\n",
- p->emis_cal[0][0], p->emis_cal[0][1], p->emis_cal[0][2]);
- a1logd(p->log,4," %f %f %f\n",
- p->emis_cal[1][0], p->emis_cal[1][1], p->emis_cal[1][2]);
- a1logd(p->log,4," %f %f %f\n",
- p->emis_cal[2][0], p->emis_cal[2][1], p->emis_cal[2][2]);
- a1logd(p->log,4,"\n");
- }
-
- } else { /* Assume matrix */
-
- /* Create the default calibration matrix */
- if ((ev = i1d3_comp_calmat(p, p->emis_cal, p->obType, p->custObserver,
- p->sens, p->sens, 3)) != inst_ok) {
- a1logd(p->log, 1, "i1d3_set_disp_type: comp_calmat dflt failed with rv = 0x%x\n",ev);
- return ev;
- }
- /* Use MIbLSr for ambient */
- if ((ev = i1d3_comp_calmat(p, p->ambi_cal, p->obType, p->custObserver, p->ambi,
- p->ambi, 3)) != inst_ok)
- return ev;
+ } else { /* Matrix */
if (dentry->flags & inst_dtflags_ccmx) {
- icmCpy3x3(p->ccmat, dentry->mat);
+ if ((ev = i1d3_set_matcal(p, dentry->mat)) != inst_ok)
+ return ev;
} else {
- icmSetUnity3x3(p->ccmat);
+ if ((ev = i1d3_set_matcal(p, NULL)) != inst_ok) /* Noop */
+ return ev;
}
}
-
- return inst_ok;
+ return i1d3_set_cal(p);
}
/* Setup the default display type */
@@ -3386,6 +3607,66 @@ i1d3_get_set_opt(inst *pp, inst_opt_type m, ...)
return inst_ok;
}
+ /* Get the current minimum integration time */
+ if (m == inst_opt_get_min_int_time) {
+ va_list args;
+ double *dpoint;
+
+ va_start(args, m);
+ dpoint = va_arg(args, double *);
+ va_end(args);
+
+ if (dpoint != NULL)
+ *dpoint = p->mininttime;
+
+ return inst_ok;
+ }
+
+ /* Set the minimum integration time */
+ if (m == inst_opt_set_min_int_time) {
+ va_list args;
+ double dval;
+
+ va_start(args, m);
+ dval = va_arg(args, double);
+ va_end(args);
+
+ p->omininttime = dval;
+
+ /* Hmm. This code is duplicated a lot.. */
+ if (p->dtype != i1d3_munkdisp && p->refrmode != 0) {
+ inst_code ev = inst_ok;
+
+ p->mininttime = 2.0 * p->dinttime;
+
+ if (p->omininttime != 0.0)
+ p->mininttime = p->omininttime; /* Override */
+
+#ifdef DEBUG_TWEAKS
+ {
+ char *cp;
+ if ((cp = getenv("I1D3_MIN_INT_TIME")) != NULL)
+ p->mininttime = atof(cp);
+ }
+#endif
+
+ /* Quantize the sample time if we have a refresh rate */
+ if (p->rrset && p->refperiod > 0.0) { /* If we have a refresh period */
+ int n;
+ n = (int)ceil(p->mininttime/p->refperiod);
+ p->inttime = n * p->refperiod;
+ a1logd(p->log, 3, "i1d3: integration time quantize to %f secs\n",p->inttime);
+
+ } else { /* We don't have a period, so simply use the double default */
+ p->inttime = p->mininttime;
+ a1logd(p->log, 3, "i1d3: integration time integration time doubled to %f secs\n",p->inttime);
+ }
+ }
+
+ return inst_ok;
+ }
+
+
/* Set the ccss observer type */
if (m == inst_opt_set_ccss_obs) {
va_list args;
@@ -3406,7 +3687,9 @@ i1d3_get_set_opt(inst *pp, inst_opt_type m, ...)
p->custObserver[2] = custObserver[2];
}
- return inst_ok;
+ a1logd(p->log, 4, "inst_opt_set_ccss_obs\n");
+
+ return i1d3_set_cal(p); /* Recompute calibration */
}
/* Operate the LEDS */
@@ -3436,6 +3719,7 @@ i1d3_get_set_opt(inst *pp, inst_opt_type m, ...)
mask = va_arg(args, int);
va_end(args);
+ p->led_state = mask;
if (p->led_state & 0x1)
return i1d3_set_LEDs(p, i1d3_flash, 0.0, 100.0, 0x80);
else
@@ -3595,9 +3879,9 @@ static void create_unlock_response(unsigned int *k, unsigned char *c, unsigned c
/* Minus the two key values as bytes */
sum += (0xff & -k[0]) + (0xff & (-k[0] >> 8))
- + (0xff & (-k[0] >> 16)) + (0xff & (-k[0] >> 24));
+ + (0xff & (-k[0] >> 16)) + (0xff & (-k[0] >> 24));
sum += (0xff & -k[1]) + (0xff & (-k[1] >> 8))
- + (0xff & (-k[1] >> 16)) + (0xff & (-k[1] >> 24));
+ + (0xff & (-k[1] >> 16)) + (0xff & (-k[1] >> 24));
/* Convert sum to bytes. Only need 2, because sum of 16 bytes can't exceed 16 bits. */
s0 = sum & 0xff;