From 094535c010320967639e8e86f974d878e80baa72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Fri, 1 May 2015 16:13:57 +0200 Subject: Imported Upstream version 1.7.0 --- spectro/munki_imp.c | 263 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 154 insertions(+), 109 deletions(-) (limited to 'spectro/munki_imp.c') diff --git a/spectro/munki_imp.c b/spectro/munki_imp.c index 9f431cc..ee7b2b1 100644 --- a/spectro/munki_imp.c +++ b/spectro/munki_imp.c @@ -165,33 +165,6 @@ 5 = dump tables etc */ -/* ============================================================ */ - -// Print bytes as hex to debug log */ -static void dump_bytes(a1log *log, char *pfx, unsigned char *buf, int base, int len) { - int i, j, ii; - char oline[200] = { '\000' }, *bp = oline; - for (i = j = 0; i < len; i++) { - if ((i % 16) == 0) - bp += sprintf(bp,"%s%04x:",pfx,base+i); - bp += sprintf(bp," %02x",buf[i]); - if ((i+1) >= len || ((i+1) % 16) == 0) { - for (ii = i; ((ii+1) % 16) != 0; ii++) - bp += sprintf(bp," "); - bp += sprintf(bp," "); - for (; j <= i; j++) { - if (!(buf[j] & 0x80) && isprint(buf[j])) - bp += sprintf(bp,"%c",buf[j]); - else - bp += sprintf(bp,"."); - } - bp += sprintf(bp,"\n"); - a1logd(log,0,"%s",oline); - bp = oline; - } - } -} - /* ============================================================ */ /* Debugging plot support */ @@ -532,23 +505,6 @@ munki_code munki_imp_init(munki *p) { return MUNKI_INT_ASSERT; } - /* Dump the eeprom contents as a block */ - if (p->log->debug >= 7) { - int base, size; - - a1logd(p->log,7, "EEPROM contents:\n"); - - size = 8192; - for (base = 0; base < (2 * 8192); base += 8192) { - unsigned char eeprom[8192]; - - if ((ev = munki_readEEProm(p, eeprom, base, size)) != MUNKI_OK) - return ev; - - dump_bytes(p->log, " ", eeprom, base, size); - } - } - /* Tick in seconds */ m->intclkp = (double)m->tickdur * 1e-6; @@ -566,6 +522,23 @@ munki_code munki_imp_init(munki *p) { if ((ev = munki_getversionstring(p, m->vstring)) != MUNKI_OK) return ev; + /* Dump the eeprom contents as a block */ + if (p->log->debug >= 7) { + int base, size; + + a1logd(p->log,7, "EEPROM contents:\n"); + + size = 1024; /* read size == buffer size */ + for (base = 0; base < (2 * 8192); base += size) { + unsigned char eeprom[1024]; + + if ((ev = munki_readEEProm(p, eeprom, base, size)) != MUNKI_OK) + return ev; + + adump_bytes(p->log, " ", eeprom, base, size); + } + } + /* Read the calibration size */ if ((ev = munki_readEEProm(p, buf, 4, 4)) != MUNKI_OK) return ev; @@ -912,6 +885,9 @@ munki_code munki_imp_get_n_a_cals(munki *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 idark_valid = cs->idark_valid; /* Current state of calib */ + int dark_valid = cs->dark_valid; + int cal_valid = cs->cal_valid; a1logd(p->log,3,"munki_imp_get_n_a_cals: checking mode %d\n",m->mmode); @@ -919,43 +895,43 @@ munki_code munki_imp_get_n_a_cals(munki *p, inst_cal_type *pn_cals, inst_cal_typ a1logd(p->log,4,"curtime %u, iddate %u, ddate %u, cfdate %u\n",curtime,cs->iddate,cs->ddate,cs->cfdate); if ((curtime - cs->iddate) > DCALTOUT) { a1logd(p->log,3,"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) > DCALTOUT) { a1logd(p->log,3,"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,3,"Invalidating white cal as %d secs from last cal\n",curtime - cs->cfdate); - cs->cal_valid = 0; + cal_valid = 0; } 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; @@ -1030,15 +1006,12 @@ munki_code munki_imp_calibrate( } a1logd(p->log,4,"munki sensor position = 0x%x\n",spos); -#ifdef NEVER /* We can set the *calc to the actual conditions, in which case */ /* the calibration will commence immediately. */ - if (!m->nosposcheck && spos == mk_spos_calib) { + if (m->nocalibask && !m->nosposcheck && spos == mk_spos_calib) { *calc = inst_calc_man_cal_smode; a1logd(p->log,4,"munki set calc to cal conditions\n",spos); - } -#endif /* Make sure that the instrument configuration matches the */ /* conditions */ @@ -1757,12 +1730,15 @@ int icoms2munki_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 { @@ -1773,7 +1749,8 @@ typedef struct { munki_code munki_imp_meas_delay( munki *p, -int *msecdelay) { /* Return the number of msec */ +int *pdispmsec, /* Return display update delay in msec */ +int *pinstmsec) { /* Return instrument reaction time in msec */ munki_code ev = MUNKI_OK; munkiimp *m = (munkiimp *)p->m; munki_state *s = &m->ms[m->mmode]; @@ -1783,10 +1760,20 @@ int *msecdelay) { /* Return the number of msec */ 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; + double stime, etime; int isdeb; + int dispmsec, instmsec; + + if (pinstmsec != NULL) + *pinstmsec = 0; + + if ((rstart = usec_time()) < 0.0) { + a1loge(p->log, inst_internal_error, "munki_imp_meas_delay: No high resolution timers\n"); + return inst_internal_error; + } /* Read the samples */ inttime = m->min_int_time; @@ -1797,16 +1784,21 @@ int *msecdelay) { /* Return the number of msec */ return MUNKI_INT_MALLOC; } -//printf("~1 %d samples at %f int\n",nummeas,inttime); if ((ev = munki_read_patches_all(p, multimeas, nummeas, &inttime, 0)) != inst_ok) { free_dmatrix(multimeas, 0, nummeas-1, 0, m->nwav-1); free(samp); return ev; } + if (m->whitestamp < 0.0) { + a1logd(p->log, 1, "munki_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; j++) { double wl = XSPECT_WL(m->wl_short, m->wl_long, m->nwav, j); @@ -1826,35 +1818,13 @@ int *msecdelay) { /* Return the number of msec */ a1logd(p->log, 3, "munki_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 - /* 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; } @@ -1868,34 +1838,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, "munki_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, "munki_meas_delay: can't detect change from white to black\n"); + a1logd(p->log, 1, "munki_meas_delay: can't detect change from black to white\n"); return MUNKI_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, "munki_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 and subtract patch change delay */ + dispmsec = (int)(samp[i].sec * 1000.0 + 0.5); + instmsec = (int)((m->trigstamp - rstart)/1000.0 + 0.5); #ifdef PLOT_UPDELAY - a1logd(p->log, 0, "munki_meas_delay: returning %d msec\n",*msecdelay); + a1logd(p->log, 0, "munki_meas_delay: disp %d, inst %d msec\n",dispmsec,instmsec); +#else + a1logd(p->log, 2, "munki_meas_delay: disp %d, inst %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, "munki_meas_delay: returning %d & %d msec\n",dispmsec,instmsec); +#else + a1logd(p->log, 2, "munki_meas_delay: returning %d & %d msec\n",dispmsec,instmsec); #endif free(samp); @@ -1904,6 +1913,21 @@ int *msecdelay) { /* Return the number of msec */ #undef NDSAMPS #undef NDMXTIME +/* Timestamp the white patch change during meas_delay() */ +inst_code munki_imp_white_change(munki *p, int init) { + munkiimp *m = (munkiimp *)p->m; + + if (init) + m->whitestamp = -1.0; + else { + if ((m->whitestamp = usec_time()) < 0.0) { + a1loge(p->log, inst_internal_error, "munki_imp_wite_change: No high resolution timers\n"); + return inst_internal_error; + } + } + + return inst_ok; +} /* - - - - - - - - - - - - - - - - */ /* Measure a patch or strip or flash in the current mode. */ @@ -2415,6 +2439,9 @@ munki_code munki_imp_meas_refrate( a1logd(p->log,2,"munki_imp_meas_refrate called\n"); + if (ref_rate != NULL) + *ref_rate = 0.0; + if (!s->emiss) { a1logd(p->log,2,"munki_imp_meas_refrate not in emissive mode\n"); return MUNKI_UNSUPPORTED; @@ -2993,9 +3020,6 @@ munki_code munki_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 MUNKI_RD_NOREFR_FOUND; } #undef NFSAMPS @@ -3983,10 +4007,12 @@ munki_code munki_ledtemp_whitemeasure( /* floating point sensor readings. Check for saturation */ if ((ev = munki_sens_to_raw(p, multimes, ledtemp, buf, ninvmeas, nummeas, m->satlimit, &darkthresh)) != MUNKI_OK) { + free(buf); free_dvector(ledtemp, 0, nummeas-1); free_dmatrix(multimes, 0, nummeas-1, -1, m->nraw-1); return ev; } + free(buf); /* Make the reference temperature nominal */ *reftemp = 0.5 * (ledtemp[0] + ledtemp[nummeas-1]); @@ -4002,7 +4028,6 @@ munki_code munki_ledtemp_whitemeasure( munki_sub_raw_to_absraw(p, nummeas, inttime, gainmode, multimes, s->dark_data, &darkthresh, 1, NULL); - free(buf); /* For each raw wavelength, compute a linear regression */ { @@ -4651,6 +4676,8 @@ munki_code munki_trialmeasure( if ((rv = munki_sens_to_raw(p, multimes, NULL, buf, 0, nmeasuered, m->satlimit, &darkthresh)) != MUNKI_OK) { if (rv != MUNKI_RD_SENSORSATURATED) { + free_dvector(absraw, -1, m->nraw-1); + free_dmatrix(multimes, 0, nummeas-1, -1, m->nraw-1); free(buf); return rv; } @@ -5360,7 +5387,7 @@ munki_code munki_extract_patches_multimeas( bdev = dev[k]; } -#ifndef NEVER +#ifndef NEVER /* Use this */ /* Weight the deviations with a triangular weighting */ /* to skew slightly towards the center */ for (k = 0; k < FW; k++) { @@ -5524,6 +5551,9 @@ munki_code munki_extract_patches_multimeas( apat = 2 * nummeas; if ((pat = (munki_patch *)malloc(sizeof(munki_patch) * apat)) == NULL) { a1logd(p->log,1,"munki: malloc of patch structures failed!\n"); + free_ivector(sizepop, 0, nummeas-1); + free_dvector(slope, 0, nummeas-1); + free_dvector(maxval, -1, m->nraw-1); return MUNKI_INT_MALLOC; } @@ -5536,6 +5566,9 @@ munki_code munki_extract_patches_multimeas( if (npat >= apat) { apat *= 2; if ((pat = (munki_patch *)realloc(pat, sizeof(munki_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,"munki: reallloc of patch structures failed!\n"); return MUNKI_INT_MALLOC; } @@ -5672,7 +5705,7 @@ munki_code munki_extract_patches_multimeas( for (i = 1; i < (npat-1); i++) { if (pat[i].use == 0) continue; - printf("Patch %d, start %d, length %d:\n",i, pat[i].ss, pat[i].no, pat[i].use); + printf("Patch %d, start %d, length %d, use %d\n",i, pat[i].ss, pat[i].no, pat[i].use); } #endif @@ -5696,7 +5729,7 @@ munki_code munki_extract_patches_multimeas( for (i = 1; i < (npat-1); i++) { if (pat[i].use == 0) continue; - printf("Patch %d, start %d, length %d:\n",i, pat[i].ss, pat[i].no, pat[i].use); + printf("Patch %d, start %d, length %d, use %d\n",i, pat[i].ss, pat[i].no, pat[i].use); } /* Create fake "slope" value that marks patches */ @@ -5997,7 +6030,7 @@ munki_code munki_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; @@ -8169,6 +8202,15 @@ a1logd(p->log,3,"set_noinitcalib v = %d, ->lo_secs %d, losecs %d secs\n",v, m->l m->noinitcalib = v; } +/* Set the nocalibask mode */ +/* Don't ask user for confirmation of calibration */ +/* if the instrument is in the correct configuration for it. */ +void munki_set_nocalibask(munki *p, int v) { + munkiimp *m = (munkiimp *)p->m; + + m->nocalibask = v; +} + /* Set the trigger config */ void munki_set_trig(munki *p, inst_opt_type trig) { munkiimp *m = (munkiimp *)p->m; @@ -8188,7 +8230,9 @@ static int munki_switch_thread(void *pp) { munkiimp *m = (munkiimp *)p->m; munki_code rv = MUNKI_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 (;;) { mk_eve ecode; rv = munki_waitfor_switch_th(p, &ecode, NULL, SW_THREAD_TIMEOUT); @@ -8291,7 +8335,7 @@ munki_readEEProm( } /* Now read the bytes */ - se = p->icom->usb_read(p->icom, NULL, 0x81, buf, size, &rwbytes, 5.0); + se = p->icom->usb_read(p->icom, NULL, 0x81, buf, size, &rwbytes, 6.0); if ((rv = icoms2munki_err(se)) != MUNKI_OK) { a1logd(p->log,1,"munki_readEEProm: read failed (2) with ICOM err 0x%x\n",se); return rv; @@ -8596,6 +8640,7 @@ munki_triggermeasure( se = p->icom->usb_control(p->icom, IUSB_ENDPOINT_OUT | IUSB_REQ_TYPE_VENDOR | IUSB_REQ_RECIP_DEVICE, 0x80, 0, 0, pbuf, 12, 2.0); + m->trigstamp = usec_time(); m->tr_t2 = msec_time(); /* Diagnostic */ @@ -8611,7 +8656,7 @@ munki_triggermeasure( /* Read a measurements results. */ /* A buffer full of bytes is returned. */ -munki_code +static munki_code munki_readmeasurement( munki *p, int inummeas, /* Initial number of measurements to expect */ -- cgit v1.2.3