summaryrefslogtreecommitdiff
path: root/spectro/ss.c
diff options
context:
space:
mode:
Diffstat (limited to 'spectro/ss.c')
-rw-r--r--spectro/ss.c163
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;