diff options
Diffstat (limited to 'spectro/ss.c')
-rw-r--r-- | spectro/ss.c | 163 |
1 files changed, 148 insertions, 15 deletions
diff --git a/spectro/ss.c b/spectro/ss.c index 837e264..260df4a 100644 --- a/spectro/ss.c +++ b/spectro/ss.c @@ -43,17 +43,20 @@ There is a bug or limitation with using -N to skip the calibration when using any of the emissive modes - the readings end up being nearly zero. + When -N is used, doing a manual calibration (i.e. spotread 'k') doesn't + work. + We aren't saving the spectrolino fake tranmission white reference in a calibration file, so -N doesn't work with it. You can't trigger a calibration reading using the instrument switch. - You should be able to do use the table enter key anywhere the user + You should be able to use the table enter key anywhere the user is asked to hit a key. The corner positioning could be smarter. - The SpectroscanT transmission cal. merely reminds the user (vie verbose) + The SpectroscanT transmission cal. merely reminds the user (via verbose) that it is assuming the correct apatture, rather than given them a chance to change it. @@ -78,6 +81,7 @@ #include "conv.h" #include "icoms.h" #include "ss.h" +#include "xrga.h" /* Default flow control */ #define DEFFC fc_Hardware @@ -97,6 +101,17 @@ char* filter_desc[] = { "Custon Filter" }; +/* Filter id */ +inst_calc_id_type filter_id[] = { + inst_calc_id_filt_unkn, + inst_calc_id_filt_none, + inst_calc_id_filt_pol, + inst_calc_id_filt_D65, + inst_calc_id_filt_unkn, + inst_calc_id_filt_UV, + inst_calc_id_filt_cust +}; + #define SS_REF_CAL_COUNT 50 #define SS_TRANS_CAL_COUNT 10 @@ -165,7 +180,7 @@ ss_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { fcc1 = ss_ctt_ProtokolWithHardwareHS; fcc2 = ss_hst_Hardware; } else { - fc = fc_none; + fc = fc_None; fcc1 = ss_ctt_ProtokolWithoutXonXoff; fcc2 = ss_hst_None; } @@ -195,7 +210,7 @@ ss_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { /* Until we time out, find the correct baud rate */ for (i = ci; clock() < etime;) { a1logd(p->log, 4, "ss_init_coms: trying baud rate %d\n",i); - if ((se = p->icom->set_ser_port(p->icom, fc_none, brt[i], parity_none, + if ((se = p->icom->set_ser_port(p->icom, fc_None, brt[i], parity_none, stop_1, length_8)) != ICOM_OK) { a1logd(p->log, 1, "ss_init_coms: set_ser_port failed ICOM err 0x%x\n",se); p->snerr = icoms2ss_err(se); @@ -258,8 +273,24 @@ ss_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { return ss_inst_err(p); } + /* Make sure the Spectrolino is still talking to us. */ + ss_init_send(p); + ss_add_soreq(p, ss_ParameterRequest); + ss_command(p, SH_TMO); + + if (ss_sub_1(p) != ss_ParameterAnswer) { /* Comms failed */ + a1logd(p->log, 1, "ss_init_coms: spectrolino, instrument isn't communicating after final coms setup"); + return inst_coms_fail; + } + } else { /* Spectroscan */ + /* Reset the Spectroscan, in case Spectrolino got messed up. */ + if ((ev = ss_do_ScanInitializeDevice(p)) != inst_ok) { + a1logd(p->log, 1, "ss_init_coms: Spectroscan reset failed ICOM err 0x%x\n",ev); + return ev; + } + ss_do_SetDeviceOnline(p); /* Put the device online */ /* Make sure other communication parameters are right */ @@ -275,9 +306,19 @@ ss_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { return ss_inst_err(p); } - /* Make sure the Spectrolino is talking to us. */ + /* Make sure the Spectroscan is still talking to us. */ + ss_init_send(p); + ss_add_ssreq(p, ss_OutputStatus); + ss_command(p, SH_TMO); + + if (ss_sub_1(p) != ss_AnsPFX) { /* Comms failed */ + a1logd(p->log, 1, "ss_init_coms: spectroscan, instrument isn't communicating after final coms setup"); + return inst_coms_fail; + } + + /* Make sure the Spectrolino is talking to Spectroscan. */ if ((ev = ss_do_ScanSpectrolino(p)) != inst_ok) { - a1logd(p->log, 1, "ss_init_coms: spectroscan, instrument isn't communicating ICOM err 0x%x\n",se); + a1logd(p->log, 1, "ss_init_coms: Spectrolino isn't communicating with Spectroscan ICOM err 0x%x\n",ev); return ev; } } @@ -322,7 +363,7 @@ ss_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { || strncmp(devn, "Spectrolino",11) != 0) return inst_unknown_model; - if (p->itype == instUnknown) /* No SpectrScan */ + if (p->itype == instUnknown) /* No SpectroScan */ p->itype = instSpectrolino; } } @@ -387,6 +428,7 @@ static void ss_determine_capabilities(ss *p) { /* return non-zero on an error, with dtp error code */ static inst_code ss_init_inst(inst *pp) { + char *envv; ss *p = (ss *)pp; inst_code rv = inst_ok; @@ -395,6 +437,19 @@ ss_init_inst(inst *pp) { if (p->gotcoms == 0) return inst_internal_error; /* Must establish coms before calling init */ + p->native_calstd = xcalstd_gmdi; /* Native is GMDI */ + p->target_calstd = xcalstd_native; /* Default to native calibration */ + + /* Honor Environment override */ + if ((envv = getenv("ARGYLL_XCALSTD")) != NULL) { + if (strcmp(envv, "XRGA") == 0) + p->target_calstd = xcalstd_xrga; + else if (strcmp(envv, "XRDI") == 0) + p->target_calstd = xcalstd_xrdi; + else if (strcmp(envv, "GMDI") == 0) + p->target_calstd = xcalstd_gmdi; + } + /* Reset the instrument to a known state */ if (p->itype != instSpectrolino) { @@ -409,8 +464,9 @@ ss_init_inst(inst *pp) { return rv; if ((rv = ss_do_ReleasePaper(p)) != inst_ok) return rv; - if ((rv = ss_do_InitMotorPosition(p)) != inst_ok) - return rv; + /* Skip this since we did a ss_do_ScanInitializeDevice() */ +// if ((rv = ss_do_InitMotorPosition(p)) != inst_ok) +// return rv; if (p->log->verb) { char dn[19]; /* Device name */ @@ -642,7 +698,7 @@ struct _inst *pp) { return rv; } -static inst_code ss_calibrate_imp(ss *p, inst_cal_type *calt, inst_cal_cond *calc, char id[CALIDLEN]); +static inst_code ss_calibrate_imp(ss *p, inst_cal_type *calt, inst_cal_cond *calc, inst_calc_id_type *idtype, char id[CALIDLEN]); /* Read a sheet full of patches using xy mode */ /* Return the inst error code */ @@ -725,10 +781,11 @@ ipatch *vals) { /* Pointer to array of values */ if ( (p->need_wd_cal || p->need_t_cal) && p->noinitcalib == 0) { inst_cal_type calt = inst_calt_needed; inst_cal_cond calc = inst_calc_none; + inst_calc_id_type idtype; char id[CALIDLEN]; /* We expect this to be automatic, but handle as if it mightn't be */ - if ((rv = ss_calibrate_imp(p, &calt, &calc, id)) != inst_ok) { + if ((rv = ss_calibrate_imp(p, &calt, &calc, &idtype, id)) != inst_ok) { if (rv == inst_cal_setup) return inst_needs_cal; /* Not automatic, needs a manual setup */ if (try < notries) { @@ -819,6 +876,11 @@ ipatch *vals) { /* Pointer to array of values */ } } + /* Apply any XRGA conversion */ + ipatch_convert_xrga(vals, npatch, + p->filt == ss_aft_PolFilter ? xcalstd_pol : xcalstd_nonpol, + p->target_calstd, p->native_calstd, instClamp); + return rv; } @@ -945,10 +1007,11 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */ if ((p->need_wd_cal || p->need_t_cal) && p->noinitcalib == 0) { inst_cal_type calt = inst_calt_needed; inst_cal_cond calc = inst_calc_none; + inst_calc_id_type idtype; char id[CALIDLEN]; /* This could be automatic or need manual intervention */ - if ((rv = ss_calibrate_imp(p, &calt, &calc, id)) != inst_ok) { + if ((rv = ss_calibrate_imp(p, &calt, &calc, &idtype, id)) != inst_ok) { if (rv == inst_cal_setup) { return inst_needs_cal; /* Not automatic, needs a manual setup */ } @@ -1269,7 +1332,8 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */ } /* spectrum data is returned only if requested */ - if (p->mode & inst_mode_spectral) { + if (p->mode & inst_mode_spectral + || XCALSTD_NEEDED(p->target_calstd, p->native_calstd)) { ss_st rst; /* Return Spectrum Type (Reflectance/Density) */ ss_rvt rvf; /* Return Reference Valid Flag */ ss_aft af; /* Return filter being used (None/Pol/D65/UV/custom */ @@ -1294,6 +1358,12 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */ } } } + + /* Apply any XRGA conversion to the measurement */ + ipatch_convert_xrga(val, 1, + p->filt == ss_aft_PolFilter ? xcalstd_pol : xcalstd_nonpol, + p->target_calstd, p->native_calstd, clamp); + if (user_trig) return inst_user_trig; return rv; @@ -1342,6 +1412,7 @@ static inst_code ss_calibrate_imp( ss *p, inst_cal_type *calt, /* Calibration type to do/remaining */ inst_cal_cond *calc, /* Current condition/desired condition */ +inst_calc_id_type *idtype, /* Condition identifier type */ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */ ) { inst_code rv = inst_ok; @@ -1350,6 +1421,7 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */ ss_owrt owr; /* Original white reference */ inst_cal_type needed, available; + *idtype = inst_calc_id_none; id[0] = '\000'; a1logd(p->log, 3, "ss calibrate called with calt = 0x%x, condition 0x%x, need w %d, t %d\n", *calt, *calc, p->need_wd_cal, p->need_t_cal); @@ -1407,6 +1479,7 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */ /* Get the name of the expected white reference */ if ((rv = so_do_WhiteReferenceRequest(p, p->filt, &afilt, sp, &owr, id)) != inst_ok) return rv; + *idtype = inst_calc_id_ref_sn; if (p->noinitcalib == 0) { @@ -1457,6 +1530,7 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */ a1logd(p->log, 3, "got filt %d, want %d\n",af,p->filt); + *idtype = filter_id[p->filt]; strcpy(id, filter_desc[p->filt]); *calc = inst_calc_change_filter; return inst_cal_setup; @@ -1543,6 +1617,7 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */ if (i < 36) { *calc = inst_calc_message; + *idtype = inst_calc_id_trans_wl; strcpy(id, "Warning: Transmission light source is low at some wavelengths!"); rv = inst_ok; } @@ -1596,6 +1671,7 @@ inst_code ss_calibrate( inst *pp, inst_cal_type *calt, /* Calibration type to do/remaining */ inst_cal_cond *calc, /* Current condition/desired condition */ +inst_calc_id_type *idtype, /* Condition identifier type */ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */ ) { ss *p = (ss *)pp; @@ -1605,7 +1681,7 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */ if (!p->inited) return inst_no_init; - return ss_calibrate_imp(p, calt, calc, id); + return ss_calibrate_imp(p, calt, calc, idtype, id); } /* Insert a compensation filter in the instrument readings */ @@ -1629,7 +1705,7 @@ char *filtername } else { xspect sp; int i; - if (read_xspect(&sp, filtername) != 0) { + if (read_xspect(&sp, NULL, filtername) != 0) { return inst_wrong_setup; } if (sp.spec_n != 36 || sp.spec_wl_short != 380.0 || sp.spec_wl_long != 730.0) { @@ -1944,6 +2020,35 @@ ss_get_set_opt(inst *pp, inst_opt_type m, ...) { break; } return inst_unsupported; + + /* Set the current xcalstd */ + } else if (m == inst_opt_set_xcalstd) { + xcalstd standard; + va_list args; + + va_start(args, m); + standard = va_arg(args, xcalstd); + va_end(args); + + p->target_calstd = standard; + + return inst_ok; + + /* Get the current effective xcalstd */ + } else if (m == inst_opt_get_xcalstd) { + xcalstd *standard; + va_list args; + + va_start(args, m); + standard = va_arg(args, xcalstd *); + va_end(args); + + if (p->target_calstd == xcalstd_native) + *standard = p->native_calstd; /* If not overridden */ + else + *standard = p->target_calstd; /* Overidden std. */ + + return inst_ok; } /* Record the trigger mode */ @@ -2002,6 +2107,34 @@ ss_get_set_opt(inst *pp, inst_opt_type m, ...) { return inst_ok; } + /* Return the white calibration tile spectrum for current filter */ + if (m == inst_opt_get_cal_tile_sp) { + ss_aft raf; + ss_owrt owr; + xspect *sp; + char dtn[19]; + inst_code rv; + va_list args; + int i; + + va_start(args, m); + sp = va_arg(args, xspect *); + va_end(args); + + /* Queries the spectra of the white tile reference for the desired filter */ + if ((rv = so_do_WhiteReferenceRequest(p, p->filt, &raf, sp->spec, &owr, dtn)) != inst_ok) + return rv; + + sp->spec_n = 36; + sp->spec_wl_short = 380; + sp->spec_wl_long = 730; + sp->norm = 100.0; + for (i = 0; i < sp->spec_n; i++) + sp->spec[i] *= 100.0; + + return inst_ok; + } + /* Use default implementation of other inst_opt_type's */ { va_list args; |