summaryrefslogtreecommitdiff
path: root/spectro/dispsup.c
diff options
context:
space:
mode:
Diffstat (limited to 'spectro/dispsup.c')
-rw-r--r--spectro/dispsup.c572
1 files changed, 340 insertions, 232 deletions
diff --git a/spectro/dispsup.c b/spectro/dispsup.c
index 0dc29ad..a27dab0 100644
--- a/spectro/dispsup.c
+++ b/spectro/dispsup.c
@@ -44,6 +44,9 @@
#include "dispwin.h"
#include "dispsup.h"
#include "webwin.h"
+#ifdef NT
+# include "madvrwin.h"
+#endif
#include "instappsup.h"
#undef SIMPLE_MODEL /* Make fake device well behaved */
@@ -56,9 +59,11 @@
#ifdef SIMPLE_MODEL
# undef FAKE_NOISE /* Add noise to _fake_ devices XYZ */
+# undef FAKE_UNPREDIC /* Initialise random unpredictably */
# undef FAKE_BITS /* Number of bits of significance of fake device */
#else
# define FAKE_NOISE 0.01 /* Add noise to _fake_ devices XYZ */
+# define FAKE_UNPREDIC /* Initialise random unpredictably */
# define FAKE_BITS 9 /* Number of bits of significance of fake device */
#endif
@@ -75,7 +80,7 @@ inst_code setup_display_calibrate(
) {
inst_code rv = inst_ok, ev;
dispwin *dw; /* Display window to display test patches on, NULL if none. */
- a1logd(p->log,1,"setup_display_calibrate called\n");
+ a1logd(p->log,1,"setup_display_calibrate called with calc = 0x%x\n",calc);
switch (calc) {
case inst_calc_none: /* Use this as a cleanup flag */
@@ -86,75 +91,70 @@ inst_code setup_display_calibrate(
break;
case inst_calc_emis_white:
- if (dwi->dw == NULL) {
- if (dwi->webdisp != 0) {
- if ((dwi->_dw = new_webwin(dwi->webdisp, dwi->hpatsize, dwi->vpatsize,
- dwi->ho, dwi->vo, 0, dwi->blackbg,
- p->log->verb, p->log->debug)) == NULL) {
- a1logd(p->log,1,"inst_handle_calibrate failed to create test window 0x%x\n",inst_other_error);
- return inst_other_error;
- }
- } else {
- if ((dwi->_dw = new_dispwin(dwi->disp, dwi->hpatsize, dwi->vpatsize,
- dwi->ho, dwi->vo, 0, 0, NULL, dwi->blackbg,
- dwi->override, p->log->debug)) == NULL) {
- a1logd(p->log,1,"inst_handle_calibrate failed to create test window 0x%x\n",inst_other_error);
- return inst_other_error;
- }
- }
- printf("Frequency calibration, Place instrument on test window.\n");
- printf(" Hit any key to continue,\n");
- printf(" or hit Esc or Q to abort:");
- } else {
- dwi->_dw = dwi->dw;
- }
- p->cal_gy_level = 1.0;
- dwi->_dw->set_color(dwi->_dw, 1.0, 1.0, 1.0);
- break;
-
+ case inst_calc_emis_80pc:
case inst_calc_emis_grey:
case inst_calc_emis_grey_darker:
case inst_calc_emis_grey_ligher:
if (dwi->dw == NULL) {
if (dwi->webdisp != 0) {
if ((dwi->_dw = new_webwin(dwi->webdisp, dwi->hpatsize, dwi->vpatsize,
- dwi->ho, dwi->vo, 0, dwi->blackbg,
- p->log->verb, p->log->debug)) == NULL) {
+ dwi->ho, dwi->vo, 0, 0, NULL, NULL, dwi->out_tvenc, dwi->blackbg,
+ p->log->verb, p->log->debug)) == NULL) {
a1logd(p->log,1,"inst_handle_calibrate failed to create test window 0x%x\n",inst_other_error);
return inst_other_error;
}
+#ifdef NT
+ } else if (dwi->madvrdisp != 0) {
+ if ((dwi->_dw = new_madvrwin(dwi->hpatsize, dwi->vpatsize,
+ dwi->ho, dwi->vo, 0, 0, NULL, NULL, dwi->out_tvenc, dwi->blackbg,
+ p->log->verb, p->log->debug)) == NULL) {
+ a1logd(p->log,1,"inst_handle_calibrate failed to create test window 0x%x\n",inst_other_error);
+ return inst_other_error;
+ }
+#endif /* NT */
} else {
if ((dwi->_dw = new_dispwin(dwi->disp, dwi->hpatsize, dwi->vpatsize,
- dwi->ho, dwi->vo, 0, 0, NULL, dwi->blackbg,
- dwi->override, p->log->debug)) == NULL) {
+ dwi->ho, dwi->vo, 0, 0, NULL, NULL, dwi->out_tvenc, dwi->blackbg,
+ dwi->override, p->log->debug)) == NULL) {
a1logd(p->log,1,"inst_handle_calibrate failed to create test window 0x%x\n",inst_other_error);
return inst_other_error;
}
}
- printf("Cell ratio calibration, Place instrument on test window.\n");
+ printf("Calibration: Place instrument on test window.\n");
printf(" Hit any key to continue,\n");
printf(" or hit Esc or Q to abort:");
} else {
dwi->_dw = dwi->dw;
}
- if (calc == inst_calc_emis_grey) {
- p->cal_gy_level = 0.6;
- p->cal_gy_count = 0;
- } else if (calc == inst_calc_emis_grey_darker) {
- p->cal_gy_level *= 0.7;
- p->cal_gy_count++;
- } else if (calc == inst_calc_emis_grey_ligher) {
- p->cal_gy_level *= 1.4;
- if (p->cal_gy_level > 1.0)
- p->cal_gy_level = 1.0;
- p->cal_gy_count++;
- }
- if (p->cal_gy_count > 4) {
- printf("Cell ratio calibration failed - too many tries at setting grey level.\n");
- a1logd(p->log,1,"inst_handle_calibrate too many tries at setting grey level 0x%x\n",inst_internal_error);
- return inst_internal_error;
+
+ if (calc == inst_calc_emis_white) {
+ p->cal_gy_level = 1.0;
+ dwi->_dw->set_color(dwi->_dw, 1.0, 1.0, 1.0);
+
+ } else if (calc == inst_calc_emis_80pc) {
+ p->cal_gy_level = 0.8;
+ dwi->_dw->set_color(dwi->_dw, 0.8, 0.8, 0.8);
+
+ } else {
+ if (calc == inst_calc_emis_grey) {
+ p->cal_gy_level = 0.6;
+ p->cal_gy_count = 0;
+ } else if (calc == inst_calc_emis_grey_darker) {
+ p->cal_gy_level *= 0.7;
+ p->cal_gy_count++;
+ } else if (calc == inst_calc_emis_grey_ligher) {
+ p->cal_gy_level *= 1.4;
+ if (p->cal_gy_level > 1.0)
+ p->cal_gy_level = 1.0;
+ p->cal_gy_count++;
+ }
+ if (p->cal_gy_count > 4) {
+ printf("Cell ratio calibration failed - too many tries at setting grey level.\n");
+ a1logd(p->log,1,"inst_handle_calibrate too many tries at setting grey level 0x%x\n",inst_internal_error);
+ return inst_internal_error;
+ }
+ dwi->_dw->set_color(dwi->_dw, p->cal_gy_level, p->cal_gy_level, p->cal_gy_level);
}
- dwi->_dw->set_color(dwi->_dw, p->cal_gy_level, p->cal_gy_level, p->cal_gy_level);
break;
default:
@@ -180,6 +180,10 @@ int nadaptive, /* NZ for non-adaptive mode */
int noinitcal, /* NZ to disable initial instrument calibration */
disppath *disp, /* display to calibrate. */
int webdisp, /* If nz, port number for web display */
+#ifdef NT
+int madvrdisp, /* NZ for MadVR display */
+#endif
+int out_tvenc, /* 1 = use RGB Video Level encoding */
int blackbg, /* NZ if whole screen should be filled with black */
int override, /* Override_redirect on X11 */
double hpatsize, /* Size of dispwin */
@@ -201,7 +205,11 @@ a1log *log /* Verb, debug & error log */
memset((void *)&dwi, 0, sizeof(disp_win_info));
dwi.webdisp = webdisp;
+#ifdef NT
+ dwi.madvrdisp = madvrdisp;
+#endif
dwi.disp = disp;
+ dwi.out_tvenc = out_tvenc;
dwi.blackbg = blackbg;
dwi.override = override;
dwi.hpatsize = hpatsize;
@@ -209,8 +217,6 @@ a1log *log /* Verb, debug & error log */
dwi.ho = ho;
dwi.vo = vo;
- p->log = new_a1log_d(log);
-
a1logv(log, 1, "Setting up the instrument\n");
if ((p = new_inst(ipath, 0, log, DUIH_FUNC_AND_CONTEXT)) == NULL) {
@@ -218,6 +224,8 @@ a1log *log /* Verb, debug & error log */
return -1;
}
+ p->log = new_a1log_d(log);
+
/* Establish communications */
if ((rv = p->init_coms(p, br, fc, 15.0)) != inst_ok) {
a1logd(p->log, 1, "init_coms returned '%s' (%s)\n",
@@ -234,6 +242,9 @@ a1log *log /* Verb, debug & error log */
return -1;
}
+// ~~~~9999 should we call config_inst_displ(p) instead of badly duplicating
+// the instrument setup here ???
+
itype = p->get_itype(p); /* Actual type */
p->capabilities(p, &cap, &cap2, &cap3);
@@ -243,6 +254,12 @@ a1log *log /* Verb, debug & error log */
tele = 0;
}
+ if (!tele && !IMODETST(cap, inst_mode_emis_spot)) {
+ printf("Want emissive spot measurement capability but instrument doesn't support it\n");
+ printf("so switching to telephoto spot mode.\n");
+ tele = 1;
+ }
+
/* Set to emission mode to read a display */
if (tele)
mode = inst_mode_emis_tele;
@@ -251,6 +268,9 @@ a1log *log /* Verb, debug & error log */
if (nadaptive)
mode |= inst_mode_emis_nonadaptive;
+// if (p->highres)
+// mode |= inst_mode_highres;
+
/* (We're assuming spectral doesn't affect calibration ?) */
if ((rv = p->set_mode(p, mode)) != inst_ok) {
@@ -308,13 +328,21 @@ a1log *log /* Verb, debug & error log */
return 0;
}
+/* Set color to black after 50msec delay */
+int del_set_black(void *cx) {
+ disprd *p = (disprd *)cx;
+ int rv;
+
+ msec_sleep(100);
+ if ((rv = p->dw->set_color(p->dw, 0.0, 0.0, 0.0)) != 0) {
+ a1logd(p->log,1,"set_color() returned %d\n",rv);
+ return 3;
+ }
+ return 0;
+}
+
/* Take a series of readings from the display - implementation */
-/* Return nz on fail/abort */
-/* 1 = user aborted */
-/* 2 = instrument access failed */
-/* 3 = window access failed */
-/* 4 = user hit terminate key */
-/* 5 = system error */
+/* Return nz on fail/abort - see dispsup.h */
/* Use disprd_err() to interpret it */
static int disprd_read_imp(
disprd *p,
@@ -350,19 +378,20 @@ static int disprd_read_imp(
/* See if we should calibrate the display update */
if (!p->update_delay_set && (cap2 & inst2_meas_disp_update) != 0) {
int cdelay, mdelay;
+ athread *th;
/* Set white with a normal delay */
if ((rv = p->dw->set_color(p->dw, 1.0, 1.0, 1.0)) != 0) {
- a1logd(p->log,1,"set_color() returned %s\n",rv);
+ a1logd(p->log,1,"set_color() returned %d\n",rv);
return 3;
}
- /* Set a zero delay */
+ /* Set a zero return delay */
cdelay = p->dw->set_update_delay(p->dw, 0);
- /* Set black with zero delay */
- if ((rv = p->dw->set_color(p->dw, 0.0, 0.0, 0.0)) != 0) {
- a1logd(p->log,1,"set_color() returned %s\n",rv);
+ /* Set black 50msec after this call */
+ if ((th = new_athread(del_set_black, (void *)p)) == NULL) {
+ a1logd(p->log,1,"failed to create thread to set_color()\n");
return 3;
}
@@ -372,24 +401,29 @@ static int disprd_read_imp(
p->it->inst_interp_error(p->it, rv), p->it->interp_error(p->it, rv));
p->dw->set_update_delay(p->dw, cdelay); /* Restore the default */
} else {
+ mdelay -= 100; /* Correct for delay on set black */
+ if (mdelay < 0)
+ mdelay = 0;
a1logv(p->log, 1, "Measured display update delay of %d msec",mdelay);
- mdelay += mdelay/2 + 50;
+ mdelay += mdelay/2 + 100;
p->dw->set_update_delay(p->dw, mdelay);
a1logv(p->log, 1, ", using delay of %d msec\n",mdelay);
}
p->update_delay_set = 1;
+ th->del(th);
}
/* See if we should do a frequency calibration or display integration time cal. first */
if (p->it->needs_calibration(p->it) & inst_calt_ref_freq
&& npat > 0
- && (cols[0].r != 1.0 || cols[0].g != 1.0 || cols[0].b != 1.0)) {
+ && (cols[0].r != 0.8 || cols[0].g != 0.8 || cols[0].b != 0.8)) {
col tc;
inst_cal_type calt = inst_calt_ref_freq;
- inst_cal_cond calc = inst_calc_emis_white;
+ inst_cal_cond calc = inst_calc_emis_80pc;
- if ((rv = p->dw->set_color(p->dw, 1.0, 1.0, 1.0)) != 0) {
- a1logd(p->log,1,"set_color() returned %s\n",rv);
+ /* Hmm. Should really ask the instrument what sort of calc it needs !!! */
+ if ((rv = p->dw->set_color(p->dw, 0.8, 0.8, 0.8)) != 0) {
+ a1logd(p->log,1,"set_color() returned %d\n",rv);
return 3;
}
/* Do calibrate, but ignore return code. Press on regardless. */
@@ -406,7 +440,7 @@ static int disprd_read_imp(
inst_cal_cond calc = inst_calc_emis_white;
if ((rv = p->dw->set_color(p->dw, 1.0, 1.0, 1.0)) != 0) {
- a1logd(p->log,1,"set_color() returned %s\n",rv);
+ a1logd(p->log,1,"set_color() returned %d\n",rv);
return 3;
}
/* Do calibrate, but ignore return code. Press on regardless. */
@@ -425,8 +459,11 @@ static int disprd_read_imp(
scb->sp.spec_n = 0;
scb->duration = 0.0;
- if (spat != 0 && tpat != 0)
+ if (spat != 0 && tpat != 0) {
a1logv(p->log, 1, "%cpatch %d of %d",cr_char,spat + (noinc != 0 ? 0 : patch),tpat);
+ if (p->dw->set_pinfo != NULL)
+ p->dw->set_pinfo(p->dw, spat + (noinc != 0 ? 0 : patch),tpat);
+ }
a1logd(p->log,1,"About to read patch %d\n",patch);
rgb[0] = scb->r;
@@ -434,7 +471,8 @@ static int disprd_read_imp(
rgb[2] = scb->b;
/* If we are doing a soft cal, apply it to the test color */
- if (p->softcal && p->cal[0][0] >= 0.0) {
+ /* (dispwin will apply any tvenc needed) */
+ if ((p->native & 1) && p->cal[0][0] >= 0.0) {
int j;
double inputEnt_1 = (double)(p->ncal-1);
@@ -456,7 +494,7 @@ static int disprd_read_imp(
}
}
if ((rv = p->dw->set_color(p->dw, rgb[0], rgb[1], rgb[2])) != 0) {
- a1logd(p->log,1,"set_color() returned %s\n",rv);
+ a1logd(p->log,1,"set_color() returned %d\n",rv);
return 3;
}
@@ -599,12 +637,7 @@ typedef struct {
} dsamples;
/* Take a series of readings from the display - drift compensation */
-/* Return nz on fail/abort */
-/* 1 = user aborted */
-/* 2 = instrument access failed */
-/* 3 = window access failed */
-/* 4 = user hit terminate key */
-/* 5 = system error */
+/* Return nz on fail/abort - see dispsup.h */
/* Use disprd_err() to interpret it */
static int disprd_read_drift(
disprd *p,
@@ -627,7 +660,7 @@ static int disprd_read_drift(
if (p->bdrift == 0) { /* Must be just wdrift */
boff = eoff = 1;
dno = 1;
- } else if (p->bdrift == 0) { /* Must be just bdrift */
+ } else if (p->wdrift == 0) { /* Must be just bdrift */
boff = eoff = 0;
dno = 1;
} else { /* Must be both */
@@ -979,12 +1012,7 @@ static void disprd_change_drift_comp(disprd *p,
}
/* Take a series of readings from the display */
-/* Return nz on fail/abort */
-/* 1 = user aborted */
-/* 2 = instrument access failed */
-/* 3 = window access failed */
-/* 4 = user hit terminate key */
-/* 5 = system error */
+/* Return nz on fail/abort - see dispsup.h */
/* Use disprd_err() to interpret it */
static int disprd_read(
disprd *p,
@@ -1035,12 +1063,7 @@ static void disprd_get_disptype(disprd *p, int *refrmode, int *cbid) {
static int config_inst_displ(disprd *p);
/* Take an ambient reading if the instrument has the capability. */
-/* return nz on fail/abort */
-/* 1 = user aborted */
-/* 2 = instrument access failed */
-/* 4 = user hit terminate key */
-/* 5 = system error */
-/* 8 = no ambient capability */
+/* return nz on fail/abort - see dispsup.h */
/* Use disprd_err() to interpret it */
int disprd_ambient(
struct _disprd *p,
@@ -1246,12 +1269,7 @@ int disprd_ambient(
/* Test without a spectrometer using a fake device */
-/* Return nz on fail/abort */
-/* 1 = user aborted */
-/* 2 = instrument access failed */
-/* 3 = window access failed */
-/* 4 = user hit terminate key */
-/* 5 = system error */
+/* Return nz on fail/abort - see dispsup.h */
/* Use disprd_err() to interpret it */
static int disprd_fake_read(
disprd *p,
@@ -1301,9 +1319,9 @@ static int disprd_fake_read(
ooff[0] = ooff[1] = ooff[2] = 0.0; /* Output offset */
#else
/* Input offset, equivalent to RGB offsets having various values */
- doff[0] = 0.10;
+ doff[0] = 0.05;
doff[1] = 0.06;
- doff[2] = 0.08;
+ doff[2] = 0.07;
/* Output offset - equivalent to flare [range 0.0 - 1.0] */
ooff[0] = 0.03;
ooff[1] = 0.04;
@@ -1313,6 +1331,8 @@ static int disprd_fake_read(
if (icmRGBprim2matrix(white, red, green, blue, mat))
error("Fake read unexpectedly got singular matrix\n");
+ icmTranspose3x3(mat, mat); /* Convert [RGB][XYZ] to [XYZ][RGB] */
+
icmSetUnity3x3(xmat);
if (p->fake2 == 1) {
@@ -1390,14 +1410,14 @@ static int disprd_fake_read(
/* If we have a test window, display the patch color */
if (p->dw) {
inst_code rv;
- if (p->softcal) { /* Display value with calibration */
+ if (p->native & 1) { /* Apply soft calibration to display value */
if ((rv = p->dw->set_color(p->dw, crgb[0], crgb[1], crgb[2])) != 0) {
- a1logd(p->log,1,"set_color() returned %s\n",rv);
+ a1logd(p->log,1,"set_color() returned %d\n",rv);
return 3;
}
} else { /* Hardware will apply calibration */
if ((rv = p->dw->set_color(p->dw, rgb[0], rgb[1], rgb[2])) != 0) {
- a1logd(p->log,1,"set_color() returned %s\n",rv);
+ a1logd(p->log,1,"set_color() returned %d\n",rv);
return 3;
}
}
@@ -1461,12 +1481,7 @@ static int disprd_fake_read(
}
/* Test without a spectrometer using a fake ICC profile device */
-/* Return nz on fail/abort */
-/* 1 = user aborted */
-/* 2 = instrument access failed */
-/* 3 = window access failed */
-/* 4 = user hit terminate key */
-/* 5 = system error */
+/* Return nz on fail/abort - see dispsup.h */
/* Use disprd_err() to interpret it */
static int disprd_fake_read_lu(
disprd *p,
@@ -1533,7 +1548,7 @@ static int disprd_fake_read_lu(
if (p->dw) {
inst_code rv;
if ((rv = p->dw->set_color(p->dw, rgb[0], rgb[1], rgb[2])) != 0) {
- a1logd(p->log,1,"set_color() returned %s\n",rv);
+ a1logd(p->log,1,"set_color() returned %d\n",rv);
return 3;
}
}
@@ -1581,12 +1596,7 @@ static int disprd_fake_read_lu(
}
/* Use without a direct connect spectrometer using shell callout */
-/* Return nz on fail/abort */
-/* 1 = user aborted */
-/* 2 = instrument access failed */
-/* 3 = window access failed */
-/* 4 = user hit terminate key */
-/* 5 = system error */
+/* Return nz on fail/abort - see duspsup.h */
/* Use disprd_err() to interpret it */
static int disprd_fake_read_co(disprd *p,
col *cols, /* Array of patch colors to be tested */
@@ -1655,7 +1665,7 @@ static int disprd_fake_read_co(disprd *p,
if (p->dw) {
inst_code rv;
if ((rv = p->dw->set_color(p->dw, rgb[0], rgb[1], rgb[2])) != 0) {
- a1logd(p->log,1,"set_color() returned %s\n",rv);
+ a1logd(p->log,1,"set_color() returned %d\n",rv);
return 3;
}
}
@@ -1726,7 +1736,7 @@ char *disprd_err(int en) {
case 2:
return "Instrument Access Failed";
case 22:
- return "Instrument Access Failed (No PLD Pattern - have you run spyd2en ?)";
+ return "Instrument Access Failed (No PLD Pattern - have you run oeminst ?)";
case 3:
return "Window Access Failed";
case 4:
@@ -1746,7 +1756,15 @@ char *disprd_err(int en) {
case 11:
return "Instrument has no CCSS capability";
case 12:
- return "Internal: trying to set calibration when not using calibration";
+ return "Video encoding requested using nonlinear current calibration curves";
+ case 13:
+ return "Video encoding requested for MadVR display - use MadVR to set video encoding";
+ case 14:
+ return "Instrument has no set refresh rate capability";
+ case 15:
+ return "Unknown calibration display type selection";
+ case 16:
+ return "Must use BASE calibration display type selection";
}
return "Unknown";
}
@@ -1782,8 +1800,6 @@ static void disprd_del(disprd *p) {
if (p->it != NULL)
p->it->del(p->it);
if (p->dw != NULL) {
- if (p->or != NULL)
- p->dw->set_ramdac(p->dw,p->or, 0);
p->dw->del(p->dw);
}
if (p->sp2cie != NULL)
@@ -1811,6 +1827,12 @@ static int config_inst_displ(disprd *p) {
p->tele = 0;
}
+ if (!p->tele && !IMODETST(cap, inst_mode_emis_spot)) {
+ printf("Want emissive spot measurement capability but instrument doesn't support it\n");
+ printf("so switching to telephoto spot mode.\n");
+ p->tele = 1;
+ }
+
if (( p->tele && !IMODETST(cap, inst_mode_emis_tele))
|| (!p->tele && !IMODETST(cap, inst_mode_emis_spot))) {
printf("Need %s emissive measurement capability,\n", p->tele ? "telephoto" : "spot");
@@ -1866,18 +1888,19 @@ static int config_inst_displ(disprd *p) {
}
/* Set the display type */
-
if (p->dtype != 0) {
if (cap2 & inst2_disptype) {
int ix;
if ((ix = inst_get_disptype_index(p->it, p->dtype, p->docbid)) < 0) {
a1logd(p->log,1,"Display type selection '%c' is not valid for instrument\n",p->dtype);
- return 2;
+ if (p->docbid)
+ return 16;
+ return 15;
}
if ((rv = p->it->set_disptype(p->it, ix)) != inst_ok) {
- a1logd(p->log,1,"Setting display type failed failed with '%s' (%s)\n",
+ a1logd(p->log,1,"Setting display type failed with '%s' (%s)\n",
p->it->inst_interp_error(p->it, rv), p->it->interp_error(p->it, rv));
- return 2;
+ return 15;
}
} else
printf("Display type ignored - instrument doesn't support display type\n");
@@ -1899,12 +1922,7 @@ static int config_inst_displ(disprd *p) {
if (p->highres) {
if (IMODETST(cap, inst_mode_highres)) {
- inst_code ev;
- if ((ev = p->it->get_set_opt(p->it, inst_opt_highres)) != inst_ok) {
- a1logd(p->log,1,"\nSetting high res mode failed with error :'%s' (%s)\n",
- p->it->inst_interp_error(p->it, ev), p->it->interp_error(p->it, ev));
- return 2;
- }
+ mode |= inst_mode_highres;
} else {
a1logv(p->log, 1, "high resolution ignored - instrument doesn't support high res. mode\n");
}
@@ -1928,19 +1946,29 @@ static int config_inst_displ(disprd *p) {
}
}
- if (p->sets != NULL
- || ((cap2 & inst2_ccss) != 0 && p->obType != icxOT_default)) {
+ /* Observer */
+ if ((cap2 & inst2_ccss) != 0 && p->obType != icxOT_default) {
if ((cap2 & inst2_ccss) == 0) {
- a1logd(p->log,1,"Instrument doesn't support ccss calibration\n");
+ a1logd(p->log,1,"Instrument doesn't support ccss calibration and we need it\n");
return 11;
}
if ((rv = p->it->get_set_opt(p->it, inst_opt_set_ccss_obs, p->obType, p->custObserver))
- != inst_ok) {
+ != inst_ok) {
a1logd(p->log,1,"inst_opt_set_ccss_obs returned '%s' (%s)\n",
p->it->inst_interp_error(p->it, rv), p->it->interp_error(p->it, rv));
return 2;
}
+ }
+
+ /* Custom CCSS */
+ if (p->sets != NULL) {
+
+ if ((cap2 & inst2_ccss) == 0) {
+ a1logd(p->log,1,"Instrument doesn't support ccss calibration and we need it\n");
+ return 11;
+ }
+
if ((rv = p->it->col_cal_spec_set(p->it, p->sets, p->no_sets)) != inst_ok) {
a1logd(p->log,1,"col_cal_spec_set returned '%s' (%s)\n",
p->it->inst_interp_error(p->it, rv), p->it->interp_error(p->it, rv));
@@ -1948,6 +1976,19 @@ static int config_inst_displ(disprd *p) {
}
}
+ if (p->refrate > 0.0) {
+ if (!(cap2 & inst2_set_refresh_rate)) {
+ a1logd(p->log,1,"Instrument doesn't support setting refresh rate\n");
+ return 11;
+ } else {
+ if ((rv = p->it->set_refr_rate(p->it, p->refrate)) != inst_ok) {
+ a1logd(p->log,1,"set_refr_rate %f Hz returned '%s' (%s)\n",
+ p->refrate, p->it->inst_interp_error(p->it, rv), p->it->interp_error(p->it, rv));
+ return 2;
+ }
+ }
+ }
+
/* Set the trigger mode to program triggered */
if ((rv = p->it->get_set_opt(p->it,inst_opt_trig_prog)) != inst_ok) {
a1logd(p->log,1,"Setting program trigger mode failed failed with '%s' (%s)\n",
@@ -1964,20 +2005,7 @@ static int config_inst_displ(disprd *p) {
/* Create a display reading object. */
/* Return NULL if error */
-/* Set *errc to code: */
-/* 0 = no error */
-/* 1 = user aborted */
-/* 2 = instrument access failed */
-/* 22 = instrument access failed - no PLD pattern */
-/* 3 = window access failed */
-/* 4 = RAMDAC access failed */
-/* 5 = user hit terminate key */
-/* 6 = system error */
-/* 7 = CRT or LCD must be selected */
-/* 9 = spectral conversion failed */
-/* 10 = no ccmx support */
-/* 11 = no ccss support */
-/* 12 = cal to set but native != 0 */
+/* Set *errc to code. See dispsup.h */
/* Use disprd_err() to interpret *errc */
disprd *new_disprd(
int *errc, /* Error code. May be NULL (could use log for this instead?) */
@@ -1988,18 +2016,25 @@ int docbid, /* NZ to only allow cbid dtypes */
int tele, /* NZ for tele mode. Falls back to display mode */
int nadaptive, /* NZ for non-adaptive mode */
int noinitcal, /* No initial instrument calibration */
+int noinitplace, /* Don't wait for user to place instrument on screen */
int highres, /* Use high res mode if available */
-int native, /* 0 = use current current or given calibration curve */
- /* 1 = use native linear out & high precision */
-int *noramdac, /* Return nz if no ramdac access. native is set to 0 */
-double cal[3][MAX_CAL_ENT], /* Calibration set/return (cal[0][0] < 0.0 or NULL if not used) */
- /* native must be 0 if cal is set */
+double refrate, /* If != 0.0, set display refresh rate calibration */
+int native, /* X0 = use current per channel calibration curve */
+ /* X1 = set native linear output and use ramdac high precn. */
+ /* 0X = use current color management cLut (MadVR) */
+ /* 1X = disable color management cLUT (MadVR) */
+int *noramdac, /* Return nz if no ramdac access. native is set to X0 */
+int *nocm, /* Return nz if no CM cLUT access. native is set to 0X */
+double cal[3][MAX_CAL_ENT], /* Calibration (cal == NULL or cal[0][0] < 0.0 if not valid) */
int ncal, /* Number of cal[] entries */
-int softcal, /* NZ if apply cal to readings rather than hardware */
disppath *disp, /* Display to calibrate. NULL if fake and no dispwin */
+int out_tvenc, /* 1 = use RGB Video Level encoding */
int blackbg, /* NZ if whole screen should be filled with black */
int override, /* Override_redirect on X11 */
int webdisp, /* If nz, port number for web color display */
+#ifdef NT
+int madvrdisp, /* NZ for MadVR display */
+#endif
char *ccallout, /* Shell callout on set color */
char *mcallout, /* Shell callout on measure color (forced fake) */
double hpatsize, /* Size of dispwin */
@@ -2020,14 +2055,10 @@ a1log *log /* Verb, debug & error log */
disprd *p = NULL;
int ch;
inst_code rv;
+ int uout_tvenc = out_tvenc; /* tvenc to use with dispwin value setting */
if (errc != NULL) *errc = 0; /* default return code = no error */
- if (cal != NULL && cal[0][0] >= 0.0 && native != 0) {
- if (errc != NULL) *errc = 12;
- return NULL;
- }
-
/* Allocate a disprd */
if ((p = (disprd *)calloc(sizeof(disprd), 1)) == NULL) {
a1logd(log, 1, "new_disprd failed due to malloc failure\n");
@@ -2058,7 +2089,9 @@ a1log *log /* Verb, debug & error log */
p->tele = tele;
p->nadaptive = nadaptive;
p->noinitcal = noinitcal;
+ p->noinitplace = noinitplace;
p->highres = highres;
+ p->refrate = refrate;
if (mcallout != NULL)
ipath = &icomFakeDevice; /* Force fake device */
p->mcallout = mcallout;
@@ -2066,7 +2099,16 @@ a1log *log /* Verb, debug & error log */
p->br = baud_19200;
p->fc = fc;
- /* Save this in case we are using a fake device */
+ p->native = native;
+
+#ifdef FAKE_NOISE
+# ifdef FAKE_UNPREDIC
+ rand32(time(NULL));
+# endif
+#endif
+
+ /* Save this so we can return current cal, or */
+ /* in case we are using a fake device */
if (cal != NULL && cal[0][0] >= 0.0) {
int j, i;
for (j = 0; j < 3; j++) {
@@ -2075,11 +2117,9 @@ a1log *log /* Verb, debug & error log */
}
}
p->ncal = ncal;
- p->softcal = softcal;
} else {
p->cal[0][0] = -1.0;
p->ncal = 0;
- p->softcal = 0;
}
/* If non-real instrument */
@@ -2179,28 +2219,103 @@ a1log *log /* Verb, debug & error log */
if (webdisp != 0) {
/* Open web display */
- if ((p->dw = new_webwin(webdisp, hpatsize, vpatsize, ho, vo, 0, 0,
- p->log->verb, p->log->debug)) == NULL) {
+ if ((p->dw = new_webwin(webdisp, hpatsize, vpatsize, ho, vo, 0, native, noramdac, nocm,
+ uout_tvenc, 0, p->log->verb, p->log->debug)) == NULL) {
a1logd(log,1,"new_disprd failed because new_webwin failed\n");
p->del(p);
if (errc != NULL) *errc = 3;
return NULL;
}
- if (noramdac != NULL)
- *noramdac = 1;
+#ifdef NT
+ } else if (madvrdisp != 0) {
+ if (out_tvenc) {
+ a1logd(log,1,"new_disprd failed because tv_enc & MadVR window\n");
+ p->del(p);
+ if (errc != NULL) *errc = 13;
+ return NULL;
+ }
+
+ if ((p->dw = new_madvrwin(hpatsize, vpatsize, ho, vo, 0, native, noramdac, nocm, out_tvenc,
+ blackbg, p->log->verb, p->log->debug)) == NULL) {
+ a1logd(log,1,"new_disprd failed because new_madvrwin failed\n");
+ p->del(p);
+ if (errc != NULL) *errc = 3;
+ return NULL;
+ }
+#endif
} else {
+ /* Don't do tvenc on test values if we are going to do it with RAMDAC curve */
+ if (out_tvenc && (p->native & 1) == 0 && p->cal[0][0] >= 0.0) {
+ uout_tvenc = 0;
+ }
+
/* Open display window for positioning (no blackbg) */
- if ((p->dw = new_dispwin(disp, hpatsize, vpatsize, ho, vo, 0, native, noramdac, 0,
- override, p->log->debug)) == NULL) {
+ if ((p->dw = new_dispwin(disp, hpatsize, vpatsize, ho, vo, 0, native, noramdac, nocm,
+ uout_tvenc, 0, override, p->log->debug)) == NULL) {
a1logd(log,1,"new_disprd failed because new_dispwin failed\n");
p->del(p);
if (errc != NULL) *errc = 3;
return NULL;
}
+
+ /* If TV encoding using existing RAMDAC and it is not linear, */
+ /* error out, as TV encoding probably won't work properly. */
+ if (out_tvenc && (native & 1) == 0 && p->cal[0][0] < 0.0) {
+ ramdac *cr;
+ if ((cr = p->dw->get_ramdac(p->dw)) != NULL) {
+ int i, j;
+ for (i = 0; i < cr->nent; i++) {
+ double val = i/(cr->nent-1.0);
+ for (j = 0; j < 3; j++) {
+ if (fabs(val - cr->v[j][i]) > 1e-5)
+ break;
+ }
+ if (j < 3)
+ break;
+ }
+ if (i < cr->nent) {
+ a1logd(log,1,"new_disprd failed because tvenc and nonlinear RAMDAC");
+ cr->del(cr);
+ p->del(p);
+ if (errc != NULL) *errc = 12;
+ return NULL;
+ }
+ cr->del(cr);
+ }
+ }
+
+#ifdef NEVER // Don't do this - dispread doesn't save calibration when using existing.
+ /* If using exiting RAMDAC, return it */
+ if ((native & 1) == 0 && p->cal[0][0] < 0.0 && cal != NULL) {
+ ramdac *r;
+
+ if ((r = p->dw->get_ramdac(p->dw)) != NULL) {
+ int j, i;
+
+ /* Get the ramdac contents. */
+ /* We linearly interpolate from RAMDAC[nent] to cal[ncal] resolution */
+ for (i = 0; i < ncal; i++) {
+ double val, w;
+ unsigned int ix;
+
+ val = (r->nent-1.0) * i/(ncal-1.0);
+ ix = (unsigned int)floor(val); /* Coordinate */
+ if (ix > (r->nent-2))
+ ix = (r->nent-2);
+ w = val - (double)ix; /* weight */
+ for (j = 0; j < 3; j++) {
+ val = r->v[j][ix];
+ cal[j][i] = val + w * (r->v[j][ix+1] - val);
+ }
+ }
+ r->del(r);
+ }
+ }
+#endif
}
if (p->it != NULL) {
- /* Do a calibration up front, so as not to get in the users way, */
+ /* Do an instrument calibration up front, so as not to get in the users way, */
/* but ignore a CRT frequency or display integration calibration, */
/* since these will be done automatically. */
if (p->it->needs_calibration(p->it) & inst_calt_n_dfrble_mask) {
@@ -2223,30 +2338,50 @@ a1log *log /* Verb, debug & error log */
}
}
- /* Ask user to put instrument on screen */
- empty_con_chars();
- printf("Place instrument on test window.\n");
- printf("Hit Esc or Q to give up, any other key to continue:"); fflush(stdout);
- if ((ch = next_con_char()) == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') {
+ if (!p->noinitplace) {
+ inst2_capability cap2;
+
+ p->it->capabilities(p->it, NULL, &cap2, NULL);
+
+ /* Turn target on */
+ if (cap2 & inst2_has_target)
+ p->it->get_set_opt(p->it, inst_opt_set_target_state, 1);
+
+ /* Ask user to put instrument on screen */
+ empty_con_chars();
+
+ printf("Place instrument on test window.\n");
+ printf("Hit Esc or Q to give up, any other key to continue:"); fflush(stdout);
+ if ((ch = next_con_char()) == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') {
+ printf("\n");
+ a1logd(log,1,"new_disprd failed because user aborted when placing device\n");
+ if (cap2 & inst2_has_target) /* Turn target off */
+ p->it->get_set_opt(p->it, inst_opt_set_target_state, 0);
+ p->del(p);
+ if (errc != NULL) *errc = 1;
+ return NULL;
+ }
+
+ /* Turn target off */
+ if (cap2 & inst2_has_target)
+ p->it->get_set_opt(p->it, inst_opt_set_target_state, 0);
+
printf("\n");
- a1logd(log,1,"new_disprd failed because user aborted when placing device\n");
- p->del(p);
- if (errc != NULL) *errc = 1;
- return NULL;
}
- printf("\n");
- if (webdisp == 0) {
+ if (webdisp == 0
+#ifdef NT
+ && madvrdisp == 0
+#endif
+ ) {
/* Close the positioning window */
if (p->dw != NULL) {
- if (p->or != NULL)
- p->dw->set_ramdac(p->dw,p->or, 0);
p->dw->del(p->dw);
}
/* Open display window again for measurement */
- if ((p->dw = new_dispwin(disp, hpatsize, vpatsize, ho, vo, 0, native, noramdac, blackbg,
- override, p->log->debug)) == NULL) {
+ if ((p->dw = new_dispwin(disp, hpatsize, vpatsize, ho, vo, 0, native, noramdac, nocm,
+ uout_tvenc, blackbg, override, p->log->debug)) == NULL) {
a1logd(log,1,"new_disprd failed new_dispwin failed\n");
p->del(p);
if (errc != NULL) *errc = 3;
@@ -2259,84 +2394,57 @@ a1log *log /* Verb, debug & error log */
p->dw->set_callout(p->dw, ccallout);
}
- /* If we have a calibration to set */
+ /* If we have a calibration to set using the RAMDAC */
/* (This is only typically the case for disread) */
- if (!p->softcal && cal != NULL && cal[0][0] >= 0.0) {
+ if ((p->native & 1) == 0 && p->cal[0][0] >= 0.0) {
/* Save current RAMDAC so that we can restore it */
- p->or = NULL;
- if ((p->or = p->dw->get_ramdac(p->dw)) == NULL) {
+ if (p->dw->r == NULL) {
warning("Unable to read or set display RAMDAC - switching to softcal");
- p->softcal = softcal = 1;
- }
+ p->native |= 1;
/* Set the given RAMDAC so we can characterise through it */
- if (p->or != NULL) {
- ramdac *r;
+ } else {
int j, i;
- r = p->or->clone(p->or);
-
/* Set the ramdac contents. */
/* We linearly interpolate from cal[ncal] to RAMDAC[nent] resolution */
- for (i = 0; i < r->nent; i++) {
+ for (i = 0; i < p->dw->r->nent; i++) {
double val, w;
unsigned int ix;
- val = (ncal-1.0) * i/(r->nent-1.0);
+ val = (ncal-1.0) * i/(p->dw->r->nent-1.0);
ix = (unsigned int)floor(val); /* Coordinate */
if (ix > (ncal-2))
ix = (ncal-2);
w = val - (double)ix; /* weight */
for (j = 0; j < 3; j++) {
- val = cal[j][ix];
- r->v[j][i] = val + w * (cal[j][ix+1] - val);
+ val = p->cal[j][ix];
+ p->dw->r->v[j][i] = val + w * (p->cal[j][ix+1] - val);
+ /* Implement tvenc here rather than dispwin, so that the order is correct */
+ if (out_tvenc) {
+ p->dw->r->v[j][i] = ((235.0 - 16.0) * p->dw->r->v[j][i] + 16.0)/255.0;
+
+ /* For video encoding the extra bits of precision are created by bit */
+ /* shifting rather than scaling, so we need to scale the fp value to */
+ /* account for this. */
+ if (p->dw->edepth > 8)
+ p->dw->r->v[j][i] =
+ (p->dw->r->v[j][i] * 255 * (1 << (p->dw->edepth - 8)))
+ /((1 << p->dw->edepth) - 1.0);
+ }
}
}
- if (p->dw->set_ramdac(p->dw, r, 0)) {
+ if (p->dw->set_ramdac(p->dw, p->dw->r, 0)) {
a1logd(log,1,"new_disprd failed becayse set_ramdac failed\n");
a1logv(p->log, 1, "Failed to set RAMDAC to desired calibration.\n");
a1logv(p->log, 1, "Perhaps the operating system is being fussy ?\n");
- r->del(r);
- p->del(p);
if (errc != NULL) *errc = 4;
return NULL;
}
- r->del(r);
}
}
- /* Return the ramdac being used */
- if (p->or != NULL && cal != NULL) {
- ramdac *r;
- int j, i;
-
- if ((r = p->dw->get_ramdac(p->dw)) == NULL) {
- a1logd(log,1,"new_disprd failed becayse get_ramdac failed\n");
- a1logv(p->log, 1, "Failed to read current RAMDAC\n");
- p->del(p);
- if (errc != NULL) *errc = 4;
- return NULL;
- }
- /* Get the ramdac contents. */
- /* We linearly interpolate from RAMDAC[nent] to cal[ncal] resolution */
- for (i = 0; i < ncal; i++) {
- double val, w;
- unsigned int ix;
-
- val = (r->nent-1.0) * i/(ncal-1.0);
- ix = (unsigned int)floor(val); /* Coordinate */
- if (ix > (r->nent-2))
- ix = (r->nent-2);
- w = val - (double)ix; /* weight */
- for (j = 0; j < 3; j++) {
- val = r->v[j][ix];
- cal[j][i] = val + w * (r->v[j][ix+1] - val);
- }
- }
- r->del(r);
- }
-
a1logd(log,1,"new_disprd succeeded\n");
return p;
}