diff options
Diffstat (limited to 'spectro/inst.c')
-rw-r--r-- | spectro/inst.c | 401 |
1 files changed, 244 insertions, 157 deletions
diff --git a/spectro/inst.c b/spectro/inst.c index 2d3adc3..9aba1bd 100644 --- a/spectro/inst.c +++ b/spectro/inst.c @@ -46,14 +46,14 @@ #endif /* !SALONEINSTLIB */ #include "numsup.h" #include "xspect.h" -#include "ccmx.h" -#include "ccss.h" #include "conv.h" #include "insttypes.h" #include "icoms.h" #include "inst.h" #include "insttypeinst.h" +#include "ccmx.h" +#include "ccss.h" #include "sort.h" #if defined(ENABLE_FAST_SERIAL) @@ -167,6 +167,24 @@ int ix /* index into the inst_disptypesel[] */ return inst_unsupported; } +/* Get the disptech and other corresponding info for the current */ +/* selected display type. Returns disptype_unknown by default. */ +/* Because refrmode can be overridden, it may not match the refrmode */ +/* of the dtech. (Pointers may be NULL if not needed) */ +static inst_code get_disptechi( +inst *pp, +disptech *dtech, +int *refrmode, +int *cbid) { + if (dtech != NULL) + *dtech = disptech_unknown; + if (refrmode != NULL) + *refrmode = disptech_get_id(disptech_unknown)->refr; + if (cbid != NULL) + *cbid = 0; + return inst_ok; +} + /* Get a status or set or get an option (default implementation) */ inst_code inst_get_set_opt_def( inst *p, @@ -359,16 +377,25 @@ char id[CALIDLEN]) { /* Condition identifier (ie. white reference ID, filter ID) } /* Measure a display update delay. It is assumed that a */ -/* White to black change has been made to the displayed color, */ +/* black to white change has been made to the displayed color, */ /* and this will measure the time it took for the update to */ +/* (It is assumed that white_change() will be called at the time the patch */ +/* changes color.) */ /* be noticed by the instrument, up to 1.0 seconds. */ /* inst_misread will be returned on failure to find a transition. */ static inst_code meas_delay( inst *p, -int *msecdelay) { /* Return the number of msec */ +int *pdispmsec, +int *pinstmsec) { return inst_unsupported; } +/* Call used by other thread to timestamp the transition. */ +static inst_code white_change( +struct _inst *p, int init) { + return inst_unsupported; +} + \ /* Return the last calibrated refresh rate in Hz. Returns: */ /* inst_unsupported - if this instrument doesn't suport a refresh mode */ /* or is unable to retrieve the refresh rate */ @@ -407,6 +434,8 @@ char *filtername) { /* File containing compensating filter */ /* To remove the matrix, pass NULL for the matrix */ static inst_code col_cor_mat( struct _inst *p, +disptech dtech, /* Use disptech_unknown if not known */ +int cbid, /* Calibration display type base ID needed, 1 if unknown */ double mtx[3][3]) { /* XYZ matrix */ return inst_unsupported; } @@ -417,6 +446,7 @@ double mtx[3][3]) { /* XYZ matrix */ /* To set calibration back to default, pass NULL for ccss. */ static inst_code col_cal_spec_set( inst *pp, +disptech dtech, /* Use disptech_unknown if not known */ xspect *sets, int no_sets) { return inst_unsupported; @@ -487,6 +517,8 @@ static char *inst_interp_error(inst *p, inst_code ec) { return "Bad Parameter Value"; case inst_hardware_fail: return "Hardware Failure"; + case inst_system_error: + return "Operating System Error"; case inst_other_error: return "Non-specific error"; } @@ -524,6 +556,11 @@ void *cntx /* Context for callback */ icoms *icom; inst *p = NULL; + if (path == NULL) { + a1logd(log, 2, "new_inst: got NULL path\n"); + return NULL; + } + a1logd(log, 2, "new_inst: called with path '%s'\n",path->name); if ((icom = new_icoms(path, log)) == NULL) { @@ -536,8 +573,9 @@ void *cntx /* Context for callback */ itype = icom->itype; /* Instrument type if its known from usb/hid */ #if defined(ENABLE_FAST_SERIAL) - if (itype == instUnknown && !nocoms && icom->fast) + if (itype == instUnknown && !nocoms && icom->fast) { itype = fast_ser_inst_type(icom, 1, uicallback, cntx); /* Else type from serial */ + } #endif /* ENABLE_FAST_SERIAL */ #if defined(ENABLE_SERIAL) @@ -569,6 +607,8 @@ void *cntx /* Context for callback */ if (itype == instSpecbos1201 || itype == instSpecbos) p = (inst *)new_specbos(icom, itype); + if (itype == instKleinK10) + p = (inst *)new_kleink10(icom, itype); #endif /* ENABLE_SERIAL */ #ifdef ENABLE_USB @@ -588,19 +628,26 @@ void *cntx /* Context for callback */ p = (inst *)new_i1pro(icom, itype); else if (itype == instColorMunki) p = (inst *)new_munki(icom, itype); - else if (itype == instHCFR) - p = (inst *)new_hcfr(icom, itype); + else if (itype == instSpyder1) + p = (inst *)new_spyd2(icom, itype); else if (itype == instSpyder2) p = (inst *)new_spyd2(icom, itype); else if (itype == instSpyder3) p = (inst *)new_spyd2(icom, itype); else if (itype == instSpyder4) p = (inst *)new_spyd2(icom, itype); + else if (itype == instSpyder5) + p = (inst *)new_spyd2(icom, itype); else if (itype == instHuey) p = (inst *)new_huey(icom, itype); else if (itype == instSmile) p = (inst *)new_i1disp(icom, itype); - else if (itype == instColorHug) + else if (itype == instEX1) + p = (inst *)new_ex1(icom, itype); + else if (itype == instHCFR) + p = (inst *)new_hcfr(icom, itype); + else if (itype == instColorHug + || itype == instColorHug2) p = (inst *)new_colorhug(icom, itype); #endif /* ENABLE_USB */ @@ -632,6 +679,8 @@ void *cntx /* Context for callback */ p->get_disptypesel = get_disptypesel; if (p->set_disptype == NULL) p->set_disptype = set_disptype; + if (p->get_disptechi == NULL) + p->get_disptechi = get_disptechi; if (p->get_set_opt == NULL) p->get_set_opt = get_set_opt; if (p->read_chart == NULL) @@ -666,6 +715,8 @@ void *cntx /* Context for callback */ p->calibrate = calibrate; if (p->meas_delay == NULL) p->meas_delay = meas_delay; + if (p->white_change == NULL) + p->white_change = white_change; if (p->get_refr_rate == NULL) p->get_refr_rate = get_refr_rate; if (p->set_refr_rate == NULL) @@ -696,59 +747,6 @@ void *cntx /* Context for callback */ } /* --------------------------------------------------- */ -/* Display type list support */ - -/* Default display type UI selector characters: - - g Generic - n Non-refresh (Generic) - r Refresh (Generic) - - c CRT - l LCD (Generic or CCFL Backlight) - f LCD, CCFL Backlight - b LCD, RGB LED Backlight - L LCD, Wide Gamut, CCFL Backlight - B LCD, Wide Gamut, RGB LED Backlight - e LCD, White LED Backlight - o OLED - a AMOLED - p Projector (Generic) - m Plasma - - F Factory base calibration - R Raw sensor values - */ - -/* Default display technology strings: - - "Color Matching Function" - "Custom" - "CRT" - "LCD CCFL IPS" - "LCD CCFL VPA" - "LCD CCFL TFT" - "LCD CCFL Wide Gamut IPS" - "LCD CCFL Wide Gamut VPA" - "LCD CCFL Wide Gamut TFT" - "LCD White LED IPS" - "LCD White LED VPA" - "LCD White LED TFT" - "LCD RGB LED IPS" - "LCD RGB LED VPA" - "LCD RGB LED TFT" - "LED OLED" - "LED AMOLED" - "Plasma" - "LCD RG Phosphor" - "Projector RGB Filter Wheel" - "Projector RGBW Filter Wheel" - "Projector RGBCMY Filter Wheel" - "Projector" - "Unknown" - - */ - /* Free a display type list */ void inst_del_disptype_list(inst_disptypesel *list, int no) { @@ -789,6 +787,7 @@ static inst_disptypesel *expand_dlist(inst_disptypesel *list, int nlist, int *na list[nlist].desc[0] = '\000'; list[nlist].refr = 0; list[nlist].ix = 0; + list[nlist].cc_cbid = 0; list[nlist].path = NULL; list[nlist].sets = NULL; list[nlist].no_sets = 0; @@ -808,49 +807,9 @@ static inst_disptypesel *expand_dlist(inst_disptypesel *list, int nlist, int *na We treat the first selector as more important than any aliases that come after it, so we need to do two passes to resolve what gets used. -*/ - -/* Set the selection characters */ -/* return NZ if we have run out */ -/* If flag == 0, deal with all selectors */ -/* If flag == 1, deal with just primary selectors */ -/* If flag == 2, deal with just secondary selectors */ -static int set_sel(int flag, char *sel, char *usels, int *k, char *asels) { - char *d, *s, i; - - /* First remove any used chars from selector */ - for (i = 0, d = s = sel; *s != '\000'; s++, i++) { - if ((flag == 2 && i == 0) /* Ignore and keep primary selector */ - || (flag == 1 && i == 1)) { /* Ignore and keep secondary selectors */ - *d++ = *s; - continue; - } - if (usels[*s] == 0) { /* If selector is not currently used */ - *d++ = *s; - usels[*s] = 1; - } - } - *d = '\000'; - - /* Add a selector if we need one */ - if (sel[0] == '\000') { - - /* Locate the next unused selector */ - for (;;) { - if (asels[*k] == '\000') /* Run out of selectors */ - return 1; - if (usels[*k] == 0) - break; - (*k)++; - } - sel[0] = asels[*k]; - sel[1] = '\000'; - usels[sel[0]] = 1; - (*k)++; - } - return 0; -} + Use disptechs_set_sel() utility function to some of the work. +*/ /* Create the display type list */ inst_code inst_creat_disptype_list(inst *p, @@ -883,7 +842,7 @@ int doccmx /* Add matching installed ccmx files */ list[nlist-1] = sdtlist[i]; /* Struct copy */ - if (set_sel(1, list[nlist-1].sel, usels, &k, asels)) { + if (disptechs_set_sel(2, list[nlist-1].sel, usels, &k, asels)) { a1loge(p->log, 1, "inst_creat_disptype_list run out of selectors\n"); break; } @@ -902,22 +861,24 @@ int doccmx /* Add matching installed ccmx files */ if ((list = expand_dlist(list, ++nlist, &nalist)) == NULL) return inst_internal_error; - list[nlist-1].flags = inst_dtflags_ccss; + list[nlist-1].flags = inst_dtflags_ccss | inst_dtflags_ld | inst_dtflags_wr; if (ss_list[i].sel != NULL) { strncpy(list[nlist-1].sel, ss_list[i].sel, INST_DTYPE_SEL_LEN); list[nlist-1].sel[INST_DTYPE_SEL_LEN-1] = '\000'; } - if (set_sel(1, list[nlist-1].sel, usels, &k, asels)) { + if (disptechs_set_sel(2, list[nlist-1].sel, usels, &k, asels)) { a1loge(p->log, 1, "inst_creat_disptype_list run out of selectors\n"); break; } strncpy(list[nlist-1].desc, ss_list[i].desc, INST_DTYPE_DESC_LEN); list[nlist-1].desc[INST_DTYPE_DESC_LEN-1] = '\000'; + list[nlist-1].dtech = ss_list[i].dtech; list[nlist-1].refr = ss_list[i].refr; list[nlist-1].ix = 0; list[nlist-1].path = ss_list[i].path; ss_list[i].path = NULL; + list[nlist-1].cbid = 0; list[nlist-1].sets = ss_list[i].sets; ss_list[i].sets = NULL; list[nlist-1].no_sets = ss_list[i].no_sets; ss_list[i].no_sets = 0; } @@ -928,49 +889,56 @@ int doccmx /* Add matching installed ccmx files */ iccmx *ss_list; /* Just ccmx's for this instrument */ - if ((ss_list = list_iccmx(inst_name(p->itype), NULL)) == NULL) { + if ((ss_list = list_iccmx(p->itype, NULL)) == NULL) { free(list); return inst_internal_error; } for (i = 0; ss_list[i].path != NULL; i++) { - /* Check that we can find the matching base calibation */ + /* Check that there is a matching base calibation */ for (j = 0; j < nlist; j++) { - if (list[j].cbid == ss_list[i].cbid) + if (ss_list[i].cc_cbid != 0 + && list[j].cbid == ss_list[i].cc_cbid) break; } if (j >= nlist) { - a1loge(p->log, 1, "inst_creat_disptype_list can't find cbid %d for '%s'\n",list[j].cbid, list[j].path); + a1loge(p->log, 1, "inst_creat_disptype_list can't find cbid %d for '%s'\n",ss_list[i].cc_cbid, ss_list[i].path); continue; } if ((list = expand_dlist(list, ++nlist, &nalist)) == NULL) return inst_internal_error; - list[nlist-1].flags = inst_dtflags_ccmx; + list[nlist-1].flags = inst_dtflags_ccmx | inst_dtflags_ld | inst_dtflags_wr; if (ss_list[i].sel != NULL) { strncpy(list[nlist-1].sel, ss_list[i].sel, INST_DTYPE_SEL_LEN); list[nlist-1].sel[INST_DTYPE_SEL_LEN-1] = '\000'; } - if (set_sel(1, list[nlist-1].sel, usels, &k, asels)) { + if (disptechs_set_sel(2, list[nlist-1].sel, usels, &k, asels)) { a1loge(p->log, 1, "inst_creat_disptype_list run out of selectors\n"); break; } strncpy(list[nlist-1].desc, ss_list[i].desc, INST_DTYPE_DESC_LEN); list[nlist-1].desc[INST_DTYPE_DESC_LEN-1] = '\000'; + list[nlist-1].dtech = ss_list[i].dtech; list[nlist-1].refr = ss_list[i].refr; list[nlist-1].ix = list[j].ix; /* Copy underlying cal selection from base */ list[nlist-1].path = ss_list[i].path; ss_list[i].path = NULL; + list[nlist-1].cbid = 0; + list[nlist-1].cc_cbid = ss_list[i].cc_cbid; icmCpy3x3(list[nlist-1].mat, ss_list[i].mat); } } - /* Verify or delete any secondary selectors from the list */ - for (i = 0; i < nlist; i++) { - set_sel(2, list[i].sel, usels, &k, asels); - } + /* Create needed selectors */ + for (i = 0; i < nlist; i++) + disptechs_set_sel(4, list[i].sel, usels, &k, asels); + + /* Verify or delete any secondary selectors */ + for (i = 0; i < nlist; i++) + disptechs_set_sel(3, list[i].sel, usels, &k, asels); if (pndtlist != NULL) *pndtlist = nlist; @@ -984,11 +952,11 @@ int doccmx /* Add matching installed ccmx files */ /* CCMX location support */ /* return a list of installed ccmx files. */ -/* if inst != NULL, return those that match the given instrument. */ +/* if itype != instUnknown, return those that match the given instrument. */ /* The list is sorted by description and terminated by a NULL entry. */ /* If no is != NULL, return the number in the list */ /* Return NULL and -1 if there is a malloc error */ -iccmx *list_iccmx(char *inst, int *no) { +iccmx *list_iccmx(instType itype, int *no) { int i, j; iccmx *rv; @@ -1011,8 +979,9 @@ iccmx *list_iccmx(char *inst, int *no) { ccmx *cs; int len; char *pp; + disptech dtech; char *tech, *disp; - int cbid, refr; + int cc_cbid, refr; if ((cs = new_ccmx()) == NULL) { a1loge(g_log, 1, "list_iccmx: new_ccmx failed\n"); @@ -1030,7 +999,7 @@ iccmx *list_iccmx(char *inst, int *no) { } /* Skip any that don't match */ - if (inst != NULL && cs->inst != NULL && strcmp(inst, cs->inst) != 0) + if (itype != instUnknown && cs->inst != NULL && inst_enum(cs->inst) != itype) continue; a1logd(g_log, 5, "Reading '%s'\n",paths[i]); @@ -1038,7 +1007,8 @@ iccmx *list_iccmx(char *inst, int *no) { tech = ""; if ((disp = cs->disp) == NULL) disp = ""; - cbid = cs->cbid; + cc_cbid = cs->cc_cbid; + dtech = cs->dtech; refr = cs->refrmode; len = strlen(tech) + strlen(disp) + 4; if ((pp = malloc(len)) == NULL) { @@ -1071,7 +1041,8 @@ iccmx *list_iccmx(char *inst, int *no) { strcat(pp, disp); strcat(pp, ")"); rv[j].desc = pp; - rv[j].cbid = cbid; + rv[j].cc_cbid = cc_cbid; + rv[j].dtech = dtech; rv[j].refr = refr; rv[j].sel = cs->sel; cs->sel = NULL; icmCpy3x3(rv[j].mat, cs->matrix); @@ -1081,7 +1052,8 @@ iccmx *list_iccmx(char *inst, int *no) { xdg_free(paths, npaths); rv[j].path = NULL; rv[j].desc = NULL; - rv[j].cbid = 0; + rv[j].cc_cbid = 0; + rv[j].dtech = disptech_unknown; rv[j].refr = -1; rv[j].sel = NULL; if (no != NULL) @@ -1142,6 +1114,7 @@ iccss *list_iccss(int *no) { ccss *cs; int len; char *pp; + disptech dtech; char *tech, *disp; int refr; @@ -1165,6 +1138,7 @@ iccss *list_iccss(int *no) { tech = ""; if ((disp = cs->disp) == NULL) disp = ""; + dtech = cs->dtech; refr = cs->refrmode; len = strlen(tech) + strlen(disp) + 4; if ((pp = malloc(len)) == NULL) { @@ -1197,6 +1171,7 @@ iccss *list_iccss(int *no) { strcat(pp, disp); strcat(pp, ")"); rv[j].desc = pp; + rv[j].dtech = dtech; rv[j].refr = refr; rv[j].sel = cs->sel; cs->sel = NULL; rv[j].sets = cs->samples; cs->samples = NULL; @@ -1207,6 +1182,7 @@ iccss *list_iccss(int *no) { xdg_free(paths, npaths); rv[j].path = NULL; rv[j].desc = NULL; + rv[j].dtech = disptech_unknown; rv[j].refr = -1; rv[j].sel = NULL; rv[j].sets = NULL; @@ -1258,7 +1234,7 @@ instType fast_ser_inst_type( ) { instType rv = instUnknown; char buf[100]; - baud_rate brt[] = { baud_921600, baud_115200, baud_38400, baud_nc }; + baud_rate brt[] = { baud_921600, baud_115200, baud_38400, baud_9600, baud_nc }; unsigned int etime; unsigned int i; int se, len; @@ -1287,36 +1263,64 @@ instType fast_ser_inst_type( // a1logd(p->log, 5, "brt = %d\n",brt[i]); - /* See if it's a JETI specbos */ - if ((se = p->write_read(p, "*idn?\r", buf, 100, "\r", 1, 0.050)) != inst_ok) { - /* Check for user abort */ - if (uicallback != NULL) { - inst_code ev; - if ((ev = uicallback(cntx, inst_negcoms)) == inst_user_abort) { - a1logd(p->log, 5, "fser_inst_type: User aborted\n"); - return instUnknown; + if (brt[i] == baud_9600) { + /* See if it's a Klein K10 */ + + if ((se = p->write_read(p, "P0\r", 0, buf, 100, NULL, ">", 1, 0.100)) != inst_ok) { + /* Check for user abort */ + if (uicallback != NULL) { + inst_code ev; + if ((ev = uicallback(cntx, inst_negcoms)) == inst_user_abort) { + a1logd(p->log, 5, "fser_inst_type: User aborted\n"); + return instUnknown; + } } + continue; + } + len = strlen(buf); + + a1logd(p->log, 5, "len = %d\n",len); + + /* Is this a Klein K1/K8/K10 response ? */ + if (strncmp(buf, "P0K-1 ", 6) == 0 + || strncmp(buf, "P0K-8 ", 6) == 0 + || strncmp(buf, "P0K-10", 6) == 0 + || strncmp(buf, "P0KV-10", 7) == 0) { + rv = instKleinK10; + break; + } + } else { + /* See if it's a JETI specbos */ + if ((se = p->write_read(p, "*idn?\r", 0, buf, 100, NULL, "\r", 1, 0.100)) != inst_ok) { + /* Check for user abort */ + if (uicallback != NULL) { + inst_code ev; + if ((ev = uicallback(cntx, inst_negcoms)) == inst_user_abort) { + a1logd(p->log, 5, "fser_inst_type: User aborted\n"); + return instUnknown; + } + } + continue; + } + len = strlen(buf); + + a1logd(p->log, 5, "len = %d\n",len); + + /* JETI specbos returns "JETI_SBXXXX", where XXXX is the instrument type, */ + /* except for the 1201 which returns "SB05" */ + + /* Is this a JETI specbos 1201 response ? */ + if (strncmp(buf, "SB05", 4) == 0) { +// a1logd(p->log, 5, "specbos1201\n"); + rv = instSpecbos1201; + break; + } + /* Is this a JETI specbos XXXX response ? */ + if (len >= 11 && strncmp(buf, "JETI_SB", 7) == 0) { +// a1logd(p->log, 5, "specbos\n"); + rv = instSpecbos; + break; } - continue; - } - len = strlen(buf); - - a1logd(p->log, 5, "len = %d\n",len); - - /* JETI specbos returns "JETI_SBXXXX", where XXXX is the instrument type, */ - /* except for the 1201 which returns "SB05" */ - - /* Is this a JETI specbos 1201 response ? */ - if (strncmp(buf, "SB05", 4) == 0) { -// a1logd(p->log, 5, "specbos1201\n"); - rv = instSpecbos1201; - break; - } - /* Is this a JETI specbos XXXX response ? */ - if (len >= 11 && strncmp(buf, "JETI_SB", 7) == 0) { -// a1logd(p->log, 5, "specbos\n"); - rv = instSpecbos; - break; } } @@ -1357,7 +1361,7 @@ static instType ser_inst_type( baud_600, baud_300, baud_110, baud_nc }; unsigned int etime; unsigned int bi, i; - int se, len; + int se, len, bread; int xrite = 0; int ss = 0; int so = 0; @@ -1385,7 +1389,8 @@ static instType ser_inst_type( } // a1logd(p->log, 5, "brt = %d\n",brt[i]); - if ((se = p->write_read(p, ";D024\r\n", buf, 100, "\r", 1, 0.5)) != inst_ok) { + bread = 0; + if ((se = p->write_read(p, ";D024\r\n", 0, buf, 100, &bread, "\r", 1, 0.5)) != inst_ok) { /* Check for user abort */ if (uicallback != NULL) { inst_code ev; @@ -1394,7 +1399,8 @@ static instType ser_inst_type( return instUnknown; } } - continue; + if (bread == 0) + continue; } len = strlen(buf); @@ -1439,7 +1445,7 @@ static instType ser_inst_type( /* SpectroScan */ if (ss) { rv = instSpectroScan; - if ((se = p->write_read(p, ";D030\r\n", buf, 100, "\n", 1, 1.5)) == 0) { + if ((se = p->write_read(p, ";D030\r\n", 0, buf, 100, NULL, "\n", 1, 1.5)) == 0) { if (strlen(buf) >= 41) { hex2bin(&buf[5], 12); // a1logd(p->log, 5, "spectroscan type = '%s'\n",buf); @@ -1451,7 +1457,7 @@ static instType ser_inst_type( if (xrite) { /* Get the X-Rite model and version number */ - if ((se = p->write_read(p, "SV\r\n", buf, 100, ">", 1, 2.5)) != 0) + if ((se = p->write_read(p, "SV\r\n", 0, buf, 100, NULL, ">", 1, 2.5)) != 0) return instUnknown; if (strlen(buf) >= 12) { @@ -1509,6 +1515,87 @@ static void hex2bin(char *buf, int len) { #endif /* ENABLE_SERIAL */ +/* ============================================================= */ +/* inst_mode persistent storage support */ + +/* Table listing and relating masks to symbols. */ +/* Need to keep this in sync with inst.h */ +struct { + int mode; /* Mode bits */ + char *sym; /* 4 character symbol */ +} inst_mode_sym[] = { + { inst_mode_reflection, inst_mode_reflection_sym }, + { inst_mode_s_reflection, inst_mode_s_reflection_sym }, + { inst_mode_transmission, inst_mode_transmission_sym }, + { inst_mode_emission, inst_mode_emission_sym }, + + { inst_mode_spot, inst_mode_spot_sym }, + { inst_mode_strip, inst_mode_strip_sym }, + { inst_mode_xy, inst_mode_xy_sym }, + { inst_mode_chart, inst_mode_chart_sym }, + { inst_mode_ambient, inst_mode_ambient_sym }, + { inst_mode_ambient_flash, inst_mode_ambient_flash_sym }, + { inst_mode_tele, inst_mode_tele_sym }, + + { inst_mode_emis_nonadaptive, inst_mode_emis_nonadaptive_sys }, + { inst_mode_ref_uv, inst_mode_ref_uv_sym }, + { inst_mode_emis_refresh_ovd, inst_mode_emis_refresh_ovd_sym }, + { inst_mode_emis_norefresh_ovd, inst_mode_emis_norefresh_ovd_sym }, + + { inst_mode_colorimeter, inst_mode_colorimeter_sym }, + { inst_mode_spectral, inst_mode_spectral_sym }, + { inst_mode_highres, inst_mode_highres_sym }, + + { inst_mode_calibration, inst_mode_calibration_sym }, + + { 0, NULL } +}; + +/* Return a string with a symbolic encoding of the mode flags */ +void inst_mode_to_sym(char sym[MAX_INST_MODE_SYM_SZ], inst_mode mode) { + int i; + char *cp = sym; + + for (i = 0; inst_mode_sym[i].mode != 0; i++) { + if (mode & inst_mode_sym[i].mode) { + if (cp != sym) + *cp++ = '_'; + strncpy(cp, inst_mode_sym[i].sym, 4); + cp += 4; + } + } + *cp++ = '\000'; +} + +/* Return a set of mode flags that correspondf to the symbolic encoding */ +/* Return nz if a symbol wasn't recognized */ +int sym_to_inst_mode(inst_mode *mode, const char *sym) { + int i; + const char *cp = sym; + int rv = 0; + + for (*mode = 0;;) { + if (cp[0] == '\000' || cp[1] == '\000' || cp[2] == '\000' || cp[3] == '\000') + break; + + for (i = 0; inst_mode_sym[i].mode != 0; i++) { + if (strncmp(inst_mode_sym[i].sym, cp, 4) == 0) { + *mode |= inst_mode_sym[i].mode; + break; + } + } + if (inst_mode_sym[i].mode == 0) + rv = 1; + + cp += 4; + + if (*cp == '_') + cp++; + } + + return rv; +} + |