summaryrefslogtreecommitdiff
path: root/spectro/i1pro_imp.c
diff options
context:
space:
mode:
Diffstat (limited to 'spectro/i1pro_imp.c')
-rw-r--r--spectro/i1pro_imp.c280
1 files changed, 191 insertions, 89 deletions
diff --git a/spectro/i1pro_imp.c b/spectro/i1pro_imp.c
index b6d6747..9a888f9 100644
--- a/spectro/i1pro_imp.c
+++ b/spectro/i1pro_imp.c
@@ -102,10 +102,12 @@
#define ENABLE_NONLINCOR /* [Def] Enable non-linear correction */
#define ENABLE_BKDRIFTC /* [Def] Enable Emis. Black drift compensation using sheilded cell values */
#define HEURISTIC_BKDRIFTC /* [Def] Enable heusristic black drift correction */
+
#define WLCALTOUT (24 * 60 * 60) /* [24 Hrs] Wavelength calibration timeout in seconds */
-#define DCALTOUT ( 60 * 60) /* [60 Minuites] Dark Calibration timeout in seconds */
+#define DCALTOUT ( 30 * 60) /* [30 Minutes] Dark Calibration timeout in seconds */
#define DCALTOUT2 ( 1 * 60 * 60) /* [1 Hr] i1pro2 Dark Calibration timeout in seconds */
#define WCALTOUT ( 1 * 60 * 60) /* [1 Hr] White Calibration timeout in seconds */
+
#define MAXSCANTIME 20.0 /* [20] Maximum scan time in seconds */
#define SW_THREAD_TIMEOUT (10 * 60.0) /* [10 Min] Switch read thread timeout */
@@ -118,7 +120,7 @@
#undef DEBUG /* Turn on debug printfs */
#undef PLOT_DEBUG /* Use plot to show readings & processing */
#undef PLOT_REFRESH /* Plot refresh rate measurement info */
-#undef PLOT_UPDELAY /* Plot data used to determine display update delay */
+#undef PLOT_UPDELAY /* Plot data used to determine display update delay */
#undef DUMP_SCANV /* Dump scan readings to a file "i1pdump.txt" */
#undef DUMP_DARKM /* Append raw dark readings to file "i1pddump.txt" */
#undef APPEND_MEAN_EMMIS_VAL /* Append averaged uncalibrated reading to file "i1pdump.txt" */
@@ -377,8 +379,13 @@ void del_i1proimp(i1pro *p) {
m->th->del(m->th);
usb_uninit_cancel(&m->sw_cancel); /* Don't need cancel token now */
usb_uninit_cancel(&m->rd_sync); /* Don't need sync token now */
+ a1logd(p->log,5,"i1pro switch thread terminated\n");
+ }
+
+ if (m->trig_thread != NULL) {
+ m->trig_thread->del(m->trig_thread);
+ a1logd(p->log,5,"i1pro trigger thread terminated\n");
}
- a1logd(p->log,5,"i1pro switch thread terminated\n");
/* Free any per mode data */
for (i = 0; i < i1p_no_modes; i++) {
@@ -1312,20 +1319,24 @@ i1pro_code i1pro_imp_set_mode(
case i1p_refl_spot:
case i1p_refl_scan:
if (p->itype == instI1Monitor)
- return I1PRO_INT_ILLEGALMODE; /* i1Monitor */
- /* Fall through */
+ return I1PRO_INT_ILLEGALMODE; /* i1Monitor can't do reflection */
+ break;
case i1p_emiss_spot_na:
case i1p_emiss_spot:
case i1p_emiss_scan:
+ break;
case i1p_amb_spot:
case i1p_amb_flash:
+ if (!i1pro_imp_ambient(p))
+ return I1PRO_INT_ILLEGALMODE;
+ break;
case i1p_trans_spot:
case i1p_trans_scan:
- m->mmode = mmode;
break;
default:
return I1PRO_INT_ILLEGALMODE;
}
+ m->mmode = mmode;
m->spec_en = (mode & inst_mode_spectral) != 0;
if ((mode & inst_mode_highres) != 0) {
@@ -1352,6 +1363,10 @@ i1pro_code i1pro_imp_get_n_a_cals(i1pro *p, inst_cal_type *pn_cals, inst_cal_typ
time_t curtime = time(NULL);
inst_cal_type n_cals = inst_calt_none;
inst_cal_type a_cals = inst_calt_none;
+ int wl_valid = cs->wl_valid; /* Locally timed out versions of valid state */
+ int idark_valid = cs->idark_valid;
+ int dark_valid = cs->dark_valid;
+ int cal_valid = cs->cal_valid;
a1logd(p->log,2,"i1pro_imp_get_n_a_cals: checking mode %d\n",m->mmode);
@@ -1359,63 +1374,63 @@ i1pro_code i1pro_imp_get_n_a_cals(i1pro *p, inst_cal_type *pn_cals, inst_cal_typ
if (m->capabilities2 & I1PRO_CAP2_WL_LED) {
if ((curtime - cs->wldate) > WLCALTOUT) {
a1logd(p->log,2,"Invalidating wavelength cal as %d secs from last cal\n",curtime - cs->wldate);
- cs->wl_valid = 0;
+ wl_valid = 0;
}
}
- if ((curtime - cs->iddate) > ((p->itype == instI1Pro) ? DCALTOUT2 : DCALTOUT)) {
+ if ((curtime - cs->iddate) > ((p->itype == instI1Pro2) ? DCALTOUT2 : DCALTOUT)) {
a1logd(p->log,2,"Invalidating adaptive dark cal as %d secs from last cal\n",curtime - cs->iddate);
- cs->idark_valid = 0;
+ idark_valid = 0;
}
- if ((curtime - cs->ddate) > ((p->itype == instI1Pro) ? DCALTOUT2 : DCALTOUT)) {
+ if ((curtime - cs->ddate) > ((p->itype == instI1Pro2) ? DCALTOUT2 : DCALTOUT)) {
a1logd(p->log,2,"Invalidating dark cal as %d secs from last cal\n",curtime - cs->ddate);
- cs->dark_valid = 0;
+ dark_valid = 0;
}
if (!cs->emiss && (curtime - cs->cfdate) > WCALTOUT) {
a1logd(p->log,2,"Invalidating white cal as %d secs from last cal\n",curtime - cs->cfdate);
- cs->cal_valid = 0;
+ cal_valid = 0;
}
#ifdef NEVER
printf("~1 reflective = %d, adaptive = %d, emiss = %d, trans = %d, scan = %d\n",
cs->reflective, cs->adaptive, cs->emiss, cs->trans, cs->scan);
printf("~1 idark_valid = %d, dark_valid = %d, cal_valid = %d\n",
- cs->idark_valid,cs->dark_valid,cs->cal_valid);
+ idark_valid,dark_valid,cal_valid);
printf("~1 want_calib = %d, want_dcalib = %d, noinitcalib = %d\n",
cs->want_calib,cs->want_dcalib, m->noinitcalib);
#endif /* NEVER */
if (m->capabilities2 & I1PRO_CAP2_WL_LED) {
- if (!cs->wl_valid
+ if (!wl_valid
|| (cs->want_dcalib && !m->noinitcalib)) // ?? want_dcalib ??
n_cals |= inst_calt_wavelength;
a_cals |= inst_calt_wavelength;
}
if (cs->reflective) {
- if (!cs->dark_valid
+ if (!dark_valid
|| (cs->want_dcalib && !m->noinitcalib))
n_cals |= inst_calt_ref_dark;
a_cals |= inst_calt_ref_dark;
- if (!cs->cal_valid
+ if (!cal_valid
|| (cs->want_calib && !m->noinitcalib))
n_cals |= inst_calt_ref_white;
a_cals |= inst_calt_ref_white;
}
if (cs->emiss) {
- if ((!cs->adaptive && !cs->dark_valid)
- || (cs->adaptive && !cs->idark_valid)
+ if ((!cs->adaptive && !dark_valid)
+ || (cs->adaptive && !idark_valid)
|| (cs->want_dcalib && !m->noinitcalib))
n_cals |= inst_calt_em_dark;
a_cals |= inst_calt_em_dark;
}
if (cs->trans) {
- if ((!cs->adaptive && !cs->dark_valid)
- || (cs->adaptive && !cs->idark_valid)
+ if ((!cs->adaptive && !dark_valid)
+ || (cs->adaptive && !idark_valid)
|| (cs->want_dcalib && !m->noinitcalib))
n_cals |= inst_calt_trans_dark;
a_cals |= inst_calt_trans_dark;
- if (!cs->cal_valid
+ if (!cal_valid
|| (cs->want_calib && !m->noinitcalib))
n_cals |= inst_calt_trans_vwhite;
a_cals |= inst_calt_trans_vwhite;
@@ -2208,8 +2223,9 @@ i1pro_code i1pro_imp_calibrate(
s->cal_factor[0], m->white_ref[0], s->cal_factor[0],
s->cal_factor[1], m->white_ref[1], s->cal_factor[1],
!s->scan); /* Use this for emis hires fine tune if not scan */
-
- if (ev != I1PRO_RD_TRANSWHITEWARN && ev != I1PRO_OK) {
+ if (ev == I1PRO_RD_TRANSWHITEWARN) /* Shouldn't happen ? */
+ ev = I1PRO_OK;
+ if (ev != I1PRO_OK) {
m->mmode = mmode; /* Restore actual mode */
return ev;
}
@@ -2395,12 +2411,15 @@ int icoms2i1pro_err(int se) {
}
/* - - - - - - - - - - - - - - - - */
-/* Measure a display update delay. It is assumed that a */
+/* Measure a display update delay. It is assumed that */
+/* white_stamp(init) has been called, and then 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.6 seconds. */
+/* be noticed by the instrument, up to 2.0 seconds. */
+/* (It is assumed that white_change() will be called at the time the patch */
+/* changes color.) */
/* inst_misread will be returned on failure to find a transition to black. */
-#define NDMXTIME 0.7 /* Maximum time to take */
+#define NDMXTIME 2.0 /* Maximum time to take */
#define NDSAMPS 500 /* Debug samples */
typedef struct {
@@ -2411,7 +2430,8 @@ typedef struct {
i1pro_code i1pro_imp_meas_delay(
i1pro *p,
-int *msecdelay) { /* Return the number of msec */
+int *pdispmsec, /* Return display update delay in msec */
+int *pinstmsec) { /* Return instrument latency in msec */
i1pro_code ev = I1PRO_OK;
i1proimp *m = (i1proimp *)p->m;
i1pro_state *s = &m->ms[m->mmode];
@@ -2419,12 +2439,20 @@ int *msecdelay) { /* Return the number of msec */
double **multimeas; /* Spectral measurements */
int nummeas;
double rgbw[3] = { 610.0, 520.0, 460.0 };
- double ucalf = 1.0; /* usec_time calibration factor */
double inttime;
+ double rstart;
i1rgbdsamp *samp;
double stot, etot, del, thr;
- double etime;
- int isdeb;
+ double stime, etime;
+ int dispmsec, instmsec;
+
+ if (pinstmsec != NULL)
+ *pinstmsec = 0;
+
+ if ((rstart = usec_time()) < 0.0) {
+ a1loge(p->log, inst_internal_error, "i1pro_imp_meas_delay: No high resolution timers\n");
+ return inst_internal_error;
+ }
/* Read the samples */
inttime = m->min_int_time;
@@ -2435,16 +2463,23 @@ int *msecdelay) { /* Return the number of msec */
return I1PRO_INT_MALLOC;
}
-//printf("~1 %d samples at %f int\n",nummeas,inttime);
+ /* We rely on the measurement code setting m->trigstamp when the */
+ /* trigger packet is sent to the instrument */
if ((ev = i1pro_read_patches_all(p, multimeas, nummeas, &inttime, 0)) != inst_ok) {
free_dmatrix(multimeas, 0, nummeas-1, 0, m->nwav[m->highres]-1);
free(samp);
return ev;
- }
+ }
+
+ if (m->whitestamp < 0.0) {
+ a1logd(p->log, 1, "i1d3_meas_delay: White transition wasn't timestamped\n");
+ return inst_internal_error;
+ }
/* Convert the samples to RGB */
+ /* Add 10 msec fudge factor */
for (i = 0; i < nummeas; i++) {
- samp[i].sec = i * inttime;
+ samp[i].sec = i * inttime + (m->trigstamp - m->whitestamp)/1000000.0 + 0.01;
samp[i].rgb[0] = samp[i].rgb[1] = samp[i].rgb[2] = 0.0;
for (j = 0; j < m->nwav[m->highres]; j++) {
double wl = XSPECT_WL(m->wl_short[m->highres], m->wl_long[m->highres], m->nwav[m->highres], j);
@@ -2462,37 +2497,15 @@ int *msecdelay) { /* Return the number of msec */
}
free_dmatrix(multimeas, 0, nummeas-1, 0, m->nwav[m->highres]-1);
- a1logd(p->log, 3, "i1pro_measure_refresh: Read %d samples for refresh calibration\n",nummeas);
-
-#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 < nummeas && 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];
- 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, y4, NULL, NULL, nummeas);
- }
-#endif
+ a1logd(p->log, 3, "i1pro_meas_delay: Read %d samples for refresh calibration\n",nummeas);
/* Over the first 100msec, locate the maximum value */
- etime = samp[nummeas-1].sec;
+ stime = samp[0].sec;
stot = -1e9;
for (i = 0; i < nummeas; i++) {
if (samp[i].tot > stot)
stot = samp[i].tot;
- if (samp[i].sec > 0.1)
+ if ((samp[i].sec - stime) > 0.1)
break;
}
@@ -2506,34 +2519,73 @@ int *msecdelay) { /* Return the number of msec */
break;
}
- del = stot - etot;
- thr = etot + 0.30 * del; /* 30% of transition threshold */
+ del = etot - stot;
+ thr = stot + 0.30 * del; /* 30% of transition threshold */
#ifdef PLOT_UPDELAY
a1logd(p->log, 0, "i1pro_meas_delay: start tot %f end tot %f del %f, thr %f\n", stot, etot, del, thr);
#endif
+#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 < nummeas && 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];
+ 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, y4, NULL, NULL, nummeas);
+ }
+#endif
+
/* Check that there has been a transition */
if (del < 5.0) {
free(samp);
- a1logd(p->log, 1, "i1pro_meas_delay: can't detect change from white to black\n");
+ a1logd(p->log, 1, "i1pro_meas_delay: can't detect change from black to white\n");
return I1PRO_RD_NOTRANS_FOUND;
}
- /* Locate the time at which the values are above the end values */
- for (i = nummeas-1; i >= 0; i--) {
+ /* Working from the start, locate the time at which the level was above the threshold */
+ for (i = 0; i < (nummeas-1); i++) {
if (samp[i].tot > thr)
break;
}
- if (i < 0) /* Assume the update was so fast that we missed it */
- i = 0;
a1logd(p->log, 2, "i1pro_meas_delay: stoped at sample %d time %f\n",i,samp[i].sec);
- *msecdelay = (int)(samp[i].sec * 1000.0 + 0.5);
+ /* Compute overall delay */
+ dispmsec = (int)(samp[i].sec * 1000.0 + 0.5); /* Display update time */
+ instmsec = (int)((m->trigstamp - rstart)/1000.0 + 0.5); /* Reaction time */
+
+#ifdef PLOT_UPDELAY
+ a1logd(p->log, 0, "i1pro_meas_delay: disp %d, trig %d msec\n",dispmsec,instmsec);
+#else
+ a1logd(p->log, 2, "i1pro_meas_delay: disp %d, trig %d msec\n",dispmsec,instmsec);
+#endif
+
+ if (dispmsec < 0) /* This can happen if the patch generator delays it's return */
+ dispmsec = 0;
+
+ if (pdispmsec != NULL)
+ *pdispmsec = dispmsec;
+
+ if (pinstmsec != NULL)
+ *pinstmsec = instmsec;
#ifdef PLOT_UPDELAY
- a1logd(p->log, 0, "i1pro_meas_delay: returning %d msec\n",*msecdelay);
+ a1logd(p->log, 0, "i1pro_meas_delay: returning %d & %d msec\n",dispmsec,instmsec);
+#else
+ a1logd(p->log, 2, "i1pro_meas_delay: returning %d & %d msec\n",dispmsec,instmsec);
#endif
free(samp);
@@ -2542,6 +2594,22 @@ int *msecdelay) { /* Return the number of msec */
#undef NDSAMPS
#undef NDMXTIME
+/* Timestamp the white patch change during meas_delay() */
+inst_code i1pro_imp_white_change(i1pro *p, int init) {
+ i1proimp *m = (i1proimp *)p->m;
+
+ if (init)
+ m->whitestamp = -1.0;
+ else {
+ if ((m->whitestamp = usec_time()) < 0.0) {
+ a1loge(p->log, inst_internal_error, "i1pro_imp_wite_change: No high resolution timers\n");
+ return inst_internal_error;
+ }
+ }
+
+ return inst_ok;
+}
+
/* - - - - - - - - - - - - - - - - */
/* Measure a patch or strip in the current mode. */
/* To try and speed up the reaction time between */
@@ -2592,7 +2660,7 @@ i1pro_code i1pro_imp_measure(
return I1PRO_INT_WRONGPATCHES;
}
- /* Notional number of measurements, befor adaptive and not counting scan */
+ /* Notional number of measurements, before adaptive and not counting scan */
nummeas = i1pro_comp_nummeas(p, s->wreadtime, s->inttime);
/* Allocate buf for pre-measurement dark calibration */
@@ -2984,7 +3052,6 @@ i1pro_code i1pro_imp_meas_refrate(
double **multimeas; /* Spectral measurements */
int nummeas;
double rgbw[3] = { 610.0, 520.0, 460.0 };
- double ucalf = 1.0; /* usec_time calibration factor */
double inttime;
static unsigned int randn = 0x12345678;
struct {
@@ -3015,6 +3082,9 @@ i1pro_code i1pro_imp_meas_refrate(
a1logd(p->log,2,"i1pro_imp_meas_refrate called\n");
+ if (ref_rate != NULL)
+ *ref_rate = 0.0;
+
if (!s->emiss) {
a1logd(p->log,2,"i1pro_imp_meas_refrate not in emissive mode\n");
return I1PRO_UNSUPPORTED;
@@ -3063,7 +3133,7 @@ i1pro_code i1pro_imp_meas_refrate(
free_dmatrix(multimeas, 0, nummeas-1, 0, m->nwav[m->highres]-1);
nfsamps = i;
- a1logd(p->log, 3, "i1pro_measure_refresh: Read %d samples for refresh calibration\n",nfsamps);
+ a1logd(p->log, 3, "i1pro_meas_refrate: Read %d samples for refresh calibration\n",nfsamps);
#ifdef NEVER
/* Plot the raw sensor values */
@@ -3102,7 +3172,6 @@ i1pro_code i1pro_imp_meas_refrate(
/* Re-zero the sample times, and normalise the readings */
for (i = nfsamps-1; i >= 0; i--) {
samp[i].sec -= samp[0].sec;
- samp[i].sec *= ucalf;
if (samp[i].sec > maxt)
maxt = samp[i].sec;
for (j = 0; j < 3; j++) {
@@ -3116,7 +3185,7 @@ i1pro_code i1pro_imp_meas_refrate(
nbins = 1 + (int)(maxt * 1000.0 * PBPMS + 0.5);
for (j = 0; j < 3; j++) {
if ((bins[j] = (double *)calloc(sizeof(double), nbins)) == NULL) {
- a1loge(p->log, inst_internal_error, "i1pro_measure_refresh: malloc failed\n");
+ a1loge(p->log, inst_internal_error, "i1pro_meas_refrate: malloc failed\n");
return I1PRO_INT_MALLOC;
}
}
@@ -3153,7 +3222,7 @@ i1pro_code i1pro_imp_meas_refrate(
y3 = malloc(sizeof(double) * nbins);
if (xx == NULL || y1 == NULL || y2 == NULL || y3 == NULL) {
- a1loge(p->log, inst_internal_error, "i1pro_measure_refresh: malloc failed\n");
+ a1loge(p->log, inst_internal_error, "i1pro_meas_refrate: malloc failed\n");
for (j = 0; j < 3; j++)
free(bins[j]);
return I1PRO_INT_MALLOC;
@@ -3596,9 +3665,6 @@ i1pro_code i1pro_imp_meas_refrate(
a1logd(p->log, 3, "Not enough tries suceeded to determine refresh rate\n");
}
- if (ref_rate != NULL)
- *ref_rate = 0.0;
-
return I1PRO_RD_NOREFR_FOUND;
}
#undef NFSAMPS
@@ -4719,6 +4785,8 @@ i1pro_code i1pro_whitemeasure(
/* absolute linearised sensor values. */
if ((ev = i1pro_sens_to_absraw(p, multimes, buf, nummeas, *inttime, gainmode, &darkthresh))
!= I1PRO_OK) {
+ free_dmatrix(multimes, 0, nummeas-1, -1, m->nraw-1);
+ free(buf);
return ev;
}
@@ -4734,8 +4802,8 @@ i1pro_code i1pro_whitemeasure(
ev = i1pro_whitemeasure_3(p, abswav0, abswav1, absraw, optscale, nummeas,
*inttime, gainmode, targoscale, multimes, darkthresh);
- free(buf);
free_dmatrix(multimes, 0, nummeas-1, -1, m->nraw-1);
+ free(buf);
return ev;
}
@@ -4954,6 +5022,9 @@ i1pro_code i1pro2_wl_measure(
/* absolute linearised sensor values. */
if ((ev = i1pro_sens_to_absraw(p, multimes, buf, nummeas, *inttime, gainmode, &darkthresh))
!= I1PRO_OK) {
+ free_dmatrix(multimes, 0, nummeas-1, -1, m->nraw-1);
+ free_dvector(dark, -1, m->nraw-1);
+ free(buf);
return ev;
}
@@ -4993,11 +5064,17 @@ i1pro_code i1pro2_wl_measure(
#ifndef IGNORE_WHITE_INCONS
if (rv & 1) {
+ free_dmatrix(multimes, 0, nummeas-1, -1, m->nraw-1);
+ free_dvector(dark, -1, m->nraw-1);
+ free(buf);
return I1PRO_RD_WHITEREADINCONS;
}
#endif /* IGNORE_WHITE_INCONS */
if (rv & 2) {
+ free_dmatrix(multimes, 0, nummeas-1, -1, m->nraw-1);
+ free_dvector(dark, -1, m->nraw-1);
+ free(buf);
return I1PRO_RD_SENSORSATURATED;
}
@@ -5017,9 +5094,9 @@ i1pro_code i1pro2_wl_measure(
*optscale = opttarget/lhighest;
}
- free(buf);
free_dmatrix(multimes, 0, nummeas-1, -1, m->nraw-1);
free_dvector(dark, -1, m->nraw-1);
+ free(buf);
return ev;
}
@@ -5102,7 +5179,9 @@ i1pro_code i1pro_read_patches_2(
/* Take a buffer full of raw readings, and convert them to */
/* absolute linearised sensor values. */
if ((ev = i1pro_sens_to_absraw(p, multimes, buf, nmeasuered, inttime, gainmode, &darkthresh))
- != I1PRO_OK) {
+ != I1PRO_OK) {
+ free_dmatrix(absraw, 0, numpatches-1, -1, m->nraw-1);
+ free_dmatrix(multimes, 0, nmeasuered-1, -1, m->nraw-1);
return ev;
}
@@ -5184,6 +5263,7 @@ i1pro_code i1pro_read_patches_2(
}
}
}
+ free_dmatrix(multimes, 0, nmeasuered-1, -1, m->nraw-1);
if (rv & 1) {
free_dmatrix(absraw, 0, numpatches-1, -1, m->nraw-1);
@@ -5470,6 +5550,9 @@ i1pro_code i1pro_trialmeasure(
/* absolute linearised sensor values. */
if ((ev = i1pro_sens_to_absraw(p, multimes, buf, nmeasuered, *inttime, gainmode, &darkthresh))
!= I1PRO_OK) {
+ free_dvector(absraw, -1, m->nraw-1);
+ free_dmatrix(multimes, 0, nummeas-1, -1, m->nraw-1);
+ free(buf);
return ev;
}
@@ -6504,6 +6587,9 @@ i1pro_code i1pro_extract_patches_multimeas(
/* Now threshold the measurements into possible patches */
apat = 2 * nummeas;
if ((pat = (i1pro_patch *)malloc(sizeof(i1pro_patch) * apat)) == NULL) {
+ free_ivector(sizepop, 0, nummeas-1);
+ free_dvector(slope, 0, nummeas-1);
+ free_dvector(maxval, -1, m->nraw-1);
a1logd(p->log, 1, "i1pro: malloc of patch structures failed!\n");
return I1PRO_INT_MALLOC;
}
@@ -6517,6 +6603,9 @@ i1pro_code i1pro_extract_patches_multimeas(
if (npat >= apat) {
apat *= 2;
if ((pat = (i1pro_patch *)realloc(pat, sizeof(i1pro_patch) * apat)) == NULL) {
+ free_ivector(sizepop, 0, nummeas-1);
+ free_dvector(slope, 0, nummeas-1);
+ free_dvector(maxval, -1, m->nraw-1);
a1logd(p->log, 1, "i1pro: reallloc of patch structures failed!\n");
return I1PRO_INT_MALLOC;
}
@@ -6969,7 +7058,7 @@ i1pro_code i1pro_extract_patches_flash(
nsampl++;
}
- /* Average all the values over the threshold, */
+ /* Integrate all the values over the threshold, */
/* and also one either side of flash */
for (j = 0; j < m->nraw-1; j++)
pavg[j] = 0.0;
@@ -7370,7 +7459,7 @@ static double wlcal_opt1(void *vcx, double tp[]) {
ix = ((int)xv) - 1; /* Reference index of Lagrange for this xv */
if (ix < 0)
continue;
- if ((ix + 3) > cx->wl_ref_n)
+ if ((ix + 4) > cx->wl_ref_n)
break;
/* Compute interpolated value of reference using Lagrange: */
@@ -8385,7 +8474,9 @@ i1pro_code i1pro_create_hr_calfactors(i1pro *p, int eonly) {
s->cal_factor[0], m->white_ref[0], s->cal_factor[0],
s->cal_factor[1], m->white_ref[1], s->cal_factor[1],
i == i1p_refl_spot);
- if (ev != I1PRO_RD_TRANSWHITEWARN && ev != I1PRO_OK) {
+ if (ev == I1PRO_RD_TRANSWHITEWARN) /* Shouldn't happen ? */
+ ev = I1PRO_OK;
+ if (ev != I1PRO_OK) {
return ev;
}
#ifdef NEVER
@@ -8429,7 +8520,9 @@ i1pro_code i1pro_create_hr_calfactors(i1pro *p, int eonly) {
i1pro_absraw_to_abswav(p, 1, s->reflective, 1, &s->cal_factor[1], &s->white_data);
ev = i1pro_compute_white_cal(p, s->cal_factor[0], NULL, s->cal_factor[0],
s->cal_factor[1], NULL, s->cal_factor[1], 0);
- if (ev != I1PRO_RD_TRANSWHITEWARN && ev != I1PRO_OK) {
+ if (ev == I1PRO_RD_TRANSWHITEWARN) /* Ignore this ? */
+ ev = I1PRO_OK;
+ if (ev != I1PRO_OK) {
return ev;
}
}
@@ -8975,7 +9068,8 @@ i1pro_code i1pro_create_hr(i1pro *p) {
/* Our upsampling is OK for reflective and ambient cal's, */
/* but isn't so good for the emissive cal., especially */
- /* on the i1pro2. We'll get an opportunity to fix it */
+ /* on the i1pro2 which has a rather bumpy diffraction */
+ /* grating/sensor. We'll get an opportunity to fix it */
/* when we do a reflective calibration, by using the */
/* smoothness of the lamp as a reference. */
@@ -9947,20 +10041,23 @@ i1pro_code i1pro_check_white_reference1(
free_dvector(emiswav, -1, m->nraw-1);
+
/* And check them against tolerance for the illuminant. */
if (m->physfilt == 0x82) { /* UV filter */
+ a1logd(p->log,2,"Checking white reference (UV): 0.0 < avg01 %f < 0.05, 1.2 < avg2227 %f < 1.76\n",avg01,avg2227);
if (0.0 < avg01 && avg01 < 0.05
&& 1.2 < avg2227 && avg2227 < 1.76) {
return I1PRO_OK;
}
} else { /* No filter */
+ a1logd(p->log,2,"Checking white reference: 0.11 < avg01 %f < 0.22, 1.35 < avg2227 %f < 1.6\n",avg01,avg2227);
if (0.11 < avg01 && avg01 < 0.22
&& 1.35 < avg2227 && avg2227 < 1.6) {
return I1PRO_OK;
}
}
- a1logd(p->log,2,"Checking white reference failed, 0.11 < avg01 %f < 0.22, 1.35 < avg2227 %f < 1.6\n",avg01,avg2227);
+ a1logd(p->log,2,"Checking white reference failed - out of tollerance");
return I1PRO_RD_WHITEREFERROR;
}
@@ -10504,7 +10601,9 @@ int i1pro_switch_thread(void *pp) {
i1proimp *m = (i1proimp *)p->m;
i1pro_code rv = I1PRO_OK;
a1logd(p->log,3,"Switch thread started\n");
- for (nfailed = 0;nfailed < 5;) {
+// for (nfailed = 0;nfailed < 5;)
+ /* Try indefinitely, in case instrument is put to sleep */
+ for (;;) {
rv = i1pro_waitfor_switch_th(p, SW_THREAD_TIMEOUT);
a1logd(p->log,8,"Switch handler triggered with rv %d, th_term %d\n",rv,m->th_term);
if (m->th_term) {
@@ -10928,7 +11027,7 @@ i1pro_delayed_trigger(void *pp) {
se = p->icom->usb_control(p->icom,
IUSB_ENDPOINT_OUT | IUSB_REQ_TYPE_VENDOR | IUSB_REQ_RECIP_DEVICE,
0xC0, 0, 0, NULL, 0, 2.0);
-
+ m->trigstamp = usec_time();
m->tr_t2 = msec_time(); /* Diagnostic */
m->trig_se = se;
@@ -10954,8 +11053,10 @@ i1pro_triggermeasure(i1pro *p, int delay) {
/* NOTE := would be better here to create thread once, and then trigger it */
/* using a condition variable. */
- if (m->trig_thread != NULL)
+ if (m->trig_thread != NULL) {
m->trig_thread->del(m->trig_thread);
+ m->trig_thread = NULL;
+ }
m->tr_t1 = m->tr_t2 = m->tr_t3 = m->tr_t4 = m->tr_t5 = m->tr_t6 = m->tr_t7 = 0;
m->trig_delay = delay;
@@ -10981,7 +11082,7 @@ i1pro_triggermeasure(i1pro *p, int delay) {
/* between triggering the measurement and starting this read. */
/* It appears that the read can be pending before triggering though. */
/* Scan reads will also terminate if there is too great a delay beteween each read.) */
-i1pro_code
+static i1pro_code
i1pro_readmeasurement(
i1pro *p,
int inummeas, /* Initial number of measurements to expect */
@@ -11525,6 +11626,7 @@ i1pro2_delayed_trigger(void *pp) {
a1logd(p->log,2,"i1pro2_delayed_trigger: trigger Rev E @ %d msec\n",
(stime = msec_time()) - m->msec);
+ m->trigstamp = usec_time();
se = p->icom->usb_control(p->icom,
IUSB_ENDPOINT_OUT | IUSB_REQ_TYPE_VENDOR | IUSB_REQ_RECIP_DEVICE,
0xD4, 0, 0, pbuf, 14, 2.0);