summaryrefslogtreecommitdiff
path: root/spectro/spyd2.c
diff options
context:
space:
mode:
Diffstat (limited to 'spectro/spyd2.c')
-rw-r--r--spectro/spyd2.c199
1 files changed, 145 insertions, 54 deletions
diff --git a/spectro/spyd2.c b/spectro/spyd2.c
index f8f9bac..dc09cea 100644
--- a/spectro/spyd2.c
+++ b/spectro/spyd2.c
@@ -7,7 +7,7 @@
* Author: Graeme W. Gill
* Date: 17/9/2007
*
- * Copyright 2006 - 2013, Graeme W. Gill
+ * Copyright 2006 - 2014, Graeme W. Gill
* All rights reserved.
*
* (Based initially on i1disp.c)
@@ -26,7 +26,7 @@
The purchaser of a Spyder 2 instrument should have received a copy
of this firmware along with their instrument, and should therefore be able to
- enable the Argyll driver for this instrument by using the spyd2en utility
+ enable the Argyll driver for this instrument by using the oeminst utility
to create a spyd2PLD.bin file.
[ The Spyder 3 & 4 don't need a PLD firmware file. ]
@@ -1869,7 +1869,8 @@ spyd2_GetAmbientReading(
// a1logd(p->log, 4, "spyd2_GetAmbientReading: combined ambient = %f Lux\n",amb);
/* Compute the Y value */
- XYZ[1] = amb; /* cd/m^2 ??? - not very accurate, due to */
+// XYZ[1] = amb; /* cd/m^2 ??? - not very accurate, due to */
+ XYZ[1] = 3.141592654 * amb; /* Lux ??? - not very accurate, due to */
/* spectral response and/or integration angle. */
XYZ[0] = icmD50.X * XYZ[1]; /* Convert to D50 neutral */
XYZ[2] = icmD50.Z * XYZ[1];
@@ -1889,7 +1890,7 @@ xspect *spyd4_cals = NULL; /* [nocals] Device spectrum */
/* calibration data. */
static inst_code
-spyd4_set_cal(
+spyd4_set_cal_ix(
spyd2 *p, /* Object */
int ix /* Selection, 0 .. spyd4_nocals-1 */
) {
@@ -1907,8 +1908,14 @@ spyd4_set_cal(
/* default calibration selections, to be faithful to the Manufacturers */
/* intentions. */
- if (standardObserver(oc, icxOT_CIE_1931_2)) {
- return spyd2_interp_code((inst *)p, SPYD2_DISP_SEL_RANGE) ;
+ if (p->obType == icxOT_custom) {
+ oc[0] = &p->custObserver[0];
+ oc[1] = &p->custObserver[1];
+ oc[2] = &p->custObserver[2];
+ } else {
+ if (standardObserver(oc, p->obType)) {
+ return spyd2_interp_code((inst *)p, SPYD2_DISP_SEL_RANGE) ;
+ }
}
/* We compute X,Y & Z independently. */
@@ -2163,7 +2170,6 @@ spyd4_comp_calmat(
/* Copy the matrix into place */
for (i = 0; i < 7; i++) {
for (j = 0; j < 3; j++) {
-//calm[i][j] = 0.5;
p->cal_A[1][j][2+i] = calm[i][j];
}
}
@@ -2236,6 +2242,104 @@ spyd4_comp_calmat(
}
+/* Preset the calibration to a spectral sample type. */
+/* ccmat[][] is set to unity */
+static inst_code
+spyd2_set_speccal(
+ spyd2 *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, "spyd2_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;
+
+ p->icx = (99 << 1) | 1; /* Out of range index */
+
+ icmSetUnity3x3(p->ccmat); /* No matrix */
+
+ return inst_ok;
+}
+
+
+/* Preset the calibration to a matrix. The spectral type is set to none */
+static inst_code
+spyd2_set_matcal(spyd2 *p, double mtx[3][3]) {
+ if (mtx == NULL) {
+ icmSetUnity3x3(p->ccmat);
+ } else {
+ if (p->cbid == 0) {
+ a1loge(p->log, 1, "spyd2: 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
+spyd2_set_cal(spyd2 *p) {
+ inst_code ev = inst_ok;
+
+ if (p->samples != NULL && p->nsamp > 0) {
+
+ /* Create matrix for specified samples */
+ if ((ev = spyd4_comp_calmat(p, p->obType, p->custObserver, p->samples, p->nsamp))
+ != inst_ok) {
+ a1logd(p->log, 1, "spyd2_set_cal: comp_calmat ccss failed with rv = 0x%x\n",ev);
+ return ev;
+ }
+
+ p->icx = (99 << 1) | 1; /* Out of range index */
+ icmSetUnity3x3(p->ccmat); /* to be sure to be sure... */
+
+ } else {
+
+ if (p->hwver >= 7) {
+ if ((p->icx >> 1) > spyd4_nocals)
+ return inst_unsupported;
+
+ /* Create the calibration matrix from internal spectral data */
+ if ((ev = spyd4_set_cal_ix(p, p->icx >> 1)) != inst_ok)
+ return ev;
+ }
+
+ }
+
+ if (p->log->debug >= 4) {
+ int i;
+ if (p->hwver >= 7) {
+ a1logd(p->log,4,"Spectral calibration matrix:\n");
+ for (i = 0; i < 7; i++) {
+ a1logd(p->log,4," %f %f %f\n",
+ p->cal_A[1][0][2+i], p->cal_A[1][1][2+i], p->cal_A[1][2][2+i]);
+ }
+ }
+ 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;
+}
+
/* ------------------------------------------------------------ */
/* Read all the relevant register values */
@@ -2472,7 +2576,7 @@ spyd2_download_pld(
a1logd(p->log, 2, "spyd2_download_pld: called\n");
if (*spyder2_pld_size == 0 || *spyder2_pld_size == 0x11223344) {
- a1logd(p->log, 1, "spyd2_download_pld: No PLD pattern available! (have you run spyd2en ?)\n");
+ a1logd(p->log, 1, "spyd2_download_pld: No PLD pattern available! (have you run oeminst ?)\n");
return spyd2_interp_code((inst *)p, SPYD2_NO_PLD_PATTERN) ;
}
@@ -2652,8 +2756,8 @@ spyd2_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
a1logd(p->log, 2, "spyd2_init_coms: about to init coms\n");
if (p->icom->port_type(p->icom) != icomt_usb) {
- a1logd(p->log, 1, "spyd2_init_coms: coms is not the right type!\n");
- return spyd2_interp_code((inst *)p, SPYD2_UNKNOWN_MODEL);
+ a1logd(p->log, 1, "spyd2_init_coms: wrong communications type for device!\n");
+ return inst_coms_fail;
}
a1logd(p->log, 2, "spyd2_init_coms: about to init USB\n");
@@ -2864,8 +2968,9 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */
} else {
/* Check for abort */
if (p->uicallback != NULL
- && (ev = p->uicallback(p->uic_cntx, inst_armed)) == inst_user_trig)
+ && (ev = p->uicallback(p->uic_cntx, inst_armed)) == inst_user_abort) {
return ev; /* Abort */
+ }
}
if (IMODETST(p->mode, inst_mode_emis_ambient)) {
@@ -2900,6 +3005,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;
return ev;
@@ -2913,23 +3019,17 @@ inst *pp,
double mtx[3][3]
) {
spyd2 *p = (spyd2 *)pp;
+ inst_code ev = inst_ok;
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, "spyd2: can't set col_cor_mat over non base display type\n");
- inst_wrong_setup;
- }
- icmCpy3x3(p->ccmat, mtx);
- }
-
- return inst_ok;
+ if ((ev = spyd2_set_matcal(p, mtx)) != inst_ok)
+ return ev;
+
+ return spyd2_set_cal(p);
}
/* Use a Colorimeter Calibration Spectral Set to set the */
@@ -2955,11 +3055,12 @@ int no_sets
if ((ev = set_default_disp_type(p)) != inst_ok)
return ev;
} else {
- /* Use given spectral samples */
- if ((ev = spyd4_comp_calmat(p, p->obType, p->custObserver, sets, no_sets)) != inst_ok)
- return ev;
- p->icx = (99 << 1) | 1; /* Out of range index */
+ if ((ev = spyd2_set_speccal(p, sets, no_sets)) != inst_ok)
+ return ev;
+
+ ev = spyd2_set_cal(p);
}
+
return ev;
}
@@ -3031,8 +3132,8 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */
if ((*calt & inst_calt_ref_freq) && p->refrmode != 0) {
- if (*calc != inst_calc_emis_white) {
- *calc = inst_calc_emis_white;
+ if (*calc != inst_calc_emis_80pc) {
+ *calc = inst_calc_emis_80pc;
return inst_cal_setup;
}
@@ -3120,7 +3221,7 @@ spyd2_interp_error(inst *pp, int ec) {
case SPYD2_BAD_EE_SIZE:
return "Serial EEProm read size > 256";
case SPYD2_NO_PLD_PATTERN:
- return "No PLD firmware pattern is available (have you run spyd2en ?)";
+ return "No PLD firmware pattern is available (have you run oeminst ?)";
case SPYD2_NO_COMS:
return "Communications hasn't been established";
case SPYD2_NOT_INITED:
@@ -3206,6 +3307,8 @@ spyd2_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);
free(p);
}
@@ -3235,7 +3338,8 @@ inst3_capability *pcap3) {
cap2 |= inst2_prog_trig
| inst2_user_trig
| inst2_ccmx
- | inst2_refresh_rate
+ | inst2_get_refresh_rate
+ | inst2_set_refresh_rate
| inst2_emis_refr_meas
;
@@ -3386,7 +3490,7 @@ inst_disptypesel spyd4_disptypesel[8] = {
{
inst_dtflags_default,
1,
- "n",
+ "nl",
"Generic Non-Refresh Display",
0,
1
@@ -3394,7 +3498,7 @@ inst_disptypesel spyd4_disptypesel[8] = {
{
inst_dtflags_none, /* flags */
2, /* cbid */
- "r", /* sel */
+ "rc", /* sel */
"Generic Refresh Display", /* desc */
1, /* refr */
1 /* ix = hw bit + spec table << 1 */
@@ -3512,35 +3616,22 @@ static inst_code set_disp_type(spyd2 *p, inst_disptypesel *dentry) {
}
p->refrmode = refrmode;
- if (dentry->flags & inst_dtflags_ccss) {
+ if (dentry->flags & inst_dtflags_ccss) { /* Spectral sample */
- if ((ev = spyd4_comp_calmat(p, p->obType, p->custObserver, dentry->sets, dentry->no_sets))
- != inst_ok) {
- a1logd(p->log, 1, "spyd4_set_disp_type: comp_calmat ccss failed with rv = 0x%x\n",ev);
+ if ((ev = spyd2_set_speccal(p, dentry->sets, dentry->no_sets)) != inst_ok)
return ev;
- }
- p->icx = (99 << 1) | 1; /* Out of range index */
- icmSetUnity3x3(p->ccmat);
- } else {
-
- if (p->hwver >= 7) {
- if ((p->icx >> 1) > spyd4_nocals)
- return inst_unsupported;
-
- /* Create the calibration matrix */
- if ((ev = spyd4_set_cal(p, p->icx >> 1)) != inst_ok)
- return ev;
- }
+ } else { /* Matrix */
if (dentry->flags & inst_dtflags_ccmx) {
- icmCpy3x3(p->ccmat, dentry->mat);
+ if ((ev = spyd2_set_matcal(p, dentry->mat)) != inst_ok)
+ return ev;
} else {
- icmSetUnity3x3(p->ccmat);
+ if ((ev = spyd2_set_matcal(p, NULL)) != inst_ok) /* Noop */
+ return ev;
}
}
-
- return inst_ok;
+ return spyd2_set_cal(p);
}
@@ -3662,7 +3753,7 @@ spyd2_get_set_opt(inst *pp, inst_opt_type m, ...) {
p->custObserver[2] = custObserver[2];
}
- return inst_ok;
+ return spyd2_set_cal(p); /* Recompute calibration */
}
/* Operate the LED */