61
#define DBG(xxx) printf xxx ;
61
#define DBG(xxx) fprintf xxx ;
63
#define DBG(xxx) if (p->debug >= 5) fprintf xxx ;
66
68
static inst_code huey_interp_code(inst *pp, int ec);
67
69
static inst_code huey_check_unlock(huey *p);
75
77
/* Implementation */
77
79
/* Interpret an icoms error into a HUEY error */
78
static int icoms2huey_err(int se) {
80
/* If torc is nz, then a trigger or command is OK, */
81
/* othewise they are treated as an abort. */
82
static int icoms2huey_err(int se, int torc) {
79
83
if (se & ICOM_USERM) {
82
return HUEY_USER_ABORT;
87
return HUEY_USER_TRIG;
89
return HUEY_USER_CMND;
83
91
if (se == ICOM_TERM)
84
92
return HUEY_USER_TERM;
86
return HUEY_USER_TRIG;
88
return HUEY_USER_CMND;
93
return HUEY_USER_ABORT;
91
96
return HUEY_COMS_FAIL;
112
117
i1d_unlock = 0x0e, /* BBBB:- Unlock the interface */
113
118
i1d_m_red_2 = 0x13, /* B:2:W Measure the red channel in freq mode, 1,10sec */
114
119
/* B = sync mode, typically 2 */
115
i1d_m_rgb_edge_2 = 0x16, /* SSS:2:WB Measure RGB Edge period mode, 1,70sec */
120
i1d_m_rgb_edge_2 = 0x16, /* SSS:2:WB Measure RGB edge/period mode, 1.70sec, ret red */
116
121
/* 2nd return value is not used ? */
117
122
i1d_rdambient = 0x17, /* BB:2:BWB Read Ambient, 1,10sec */
118
123
/* Returns first B param as first response */
198
203
if (isdeb) fprintf(stderr,"huey: Sending cmd '%s' args '%s'",inst_desc(cc), icoms_tohex(in, 7));
200
205
/* Send the command using the control interface */
201
buf[0] = cc; /* Construct the command */
206
buf[0] = cc; /* Construct the command == HID report number */
202
207
memmove(buf + 1, in, 7);
204
209
if (p->icom->is_hid) {
218
223
return huey_interp_code((inst *)p, HUEY_COMS_FAIL);
221
rv = huey_interp_code((inst *)p, icoms2huey_err(ua));
226
rv = huey_interp_code((inst *)p, icoms2huey_err(ua, 0));
222
227
if (isdeb) fprintf(stderr," ICOM err 0x%x\n",ua);
229
if (rv == inst_ok && wbytes != 8)
224
230
rv = huey_interp_code((inst *)p, HUEY_BAD_WR_LENGTH);
225
232
if (rv != inst_ok) {
233
/* Flush any response */
234
if (p->icom->is_hid) {
235
p->icom->hid_read(p->icom, buf, 8, &rbytes, to);
237
p->icom->usb_read(p->icom, 0x81, buf, 8, &rbytes, to);
226
239
p->icom->debug = isdeb;
233
246
if (p->icom->is_hid) {
234
247
se = p->icom->hid_read(p->icom, buf, 8, &rbytes, to);
237
249
se = p->icom->usb_read(p->icom, 0x81, buf, 8, &rbytes, to);
246
258
return huey_interp_code((inst *)p, HUEY_COMS_FAIL);
249
rv = huey_interp_code((inst *)p, icoms2huey_err(ua));
261
rv = huey_interp_code((inst *)p, icoms2huey_err(ua, 0));
262
if (rv == inst_ok && rbytes != 8)
251
263
rv = huey_interp_code((inst *)p, HUEY_BAD_RD_LENGTH);
252
if (rv == inst_ok && buf[1] != cc) {
264
if (rv == inst_ok && buf[1] != cc)
253
265
rv = huey_interp_code((inst *)p, HUEY_BAD_RET_CMD);
256
267
/* Some commands don't use the first response, but need to */
257
268
/* fetch a second response, with a longer timeout. */
273
284
return huey_interp_code((inst *)p, HUEY_COMS_FAIL);
276
rv = huey_interp_code((inst *)p, icoms2huey_err(ua));
287
rv = huey_interp_code((inst *)p, icoms2huey_err(ua, 0));
288
if (rv == inst_ok && rbytes != 8)
278
289
rv = huey_interp_code((inst *)p, HUEY_BAD_RD_LENGTH);
279
290
if (rv == inst_ok && buf[1] != cc) {
280
291
rv = huey_interp_code((inst *)p, HUEY_BAD_RET_CMD);
541
552
/* - - - - - - - - - - - - - - - - - - - - - - - - */
543
/* Take a raw initial (CRT) measurement from the device for a huey */
554
/* Take a raw measurement using a given integration time. */
555
/* The measureent is the count of (both) edges from the L2V */
556
/* over the integration time */
545
huey_take_first_raw_measurement_2(
546
559
huey *p, /* Object */
547
double rgb[3] /* Return the RGB values */
560
double rgb[3] /* Return the RGB edge count values */
550
563
unsigned char ibuf[8];
573
/* Take a raw subsequent (CRT + LCD) mesurement from the device for a huey */
586
/* Take a raw measurement that returns the number of clocks */
587
/* between and initial edge and edgec[] subsequent edges of the L2F. */
588
/* Both edges are counted. */
575
huey_take_raw_measurement_2(
576
591
huey *p, /* Object */
577
592
int edgec[3], /* Measurement edge count for each channel */
578
593
double rgb[3] /* Return the RGB values */
669
684
if (p->inited == 0)
670
685
return huey_interp_code((inst *)p, HUEY_NOT_INITED);
672
DBG(("take_measurement_2 called with crtm = %d\n",crtm));
687
DBG((dbgo,"take_measurement_2 called with crtm = %d\n",crtm));
674
689
/* For CRT mode, do an initial set of syncromized measurements */
677
if ((ev = huey_take_first_raw_measurement_2(p, rgb)) != inst_ok)
692
if ((ev = huey_freq_measure(p, rgb)) != inst_ok)
680
DBG(("Raw initial CRT RGB = %f %f %f\n",rgb[0],rgb[1],rgb[2]))
695
DBG((dbgo,"Raw initial CRT RGB = %f %f %f\n",rgb[0],rgb[1],rgb[2]))
682
697
/* Decide whether any channels need re-measuring, */
683
698
/* and computed cooked values. Threshold is typically 75 */
685
700
rem[i] = (rgb[i] <= (0.75 * (double)p->sampno)) ? 1 : 0;
686
701
rgb[i] = 0.5 * rgb[i] * 1e6/(double)p->int_clocks;
688
DBG(("Re-measure flags = %d %d %d\n",rem[0],rem[1],rem[2]))
703
DBG((dbgo,"Re-measure flags = %d %d %d\n",rem[0],rem[1],rem[2]))
691
706
/* If any need re-measuring */
695
710
/* Do a first or second set of measurements */
696
if ((ev = huey_take_raw_measurement_2(p, edgec, rgb2)) != inst_ok)
711
if ((ev = huey_period_measure(p, edgec, rgb2)) != inst_ok)
698
DBG(("Raw initial/subsequent ecount %d %d %d RGB = %f %f %f\n",
713
DBG((dbgo,"Raw initial/subsequent ecount %d %d %d RGB = %f %f %f\n",
699
714
edgec[0], edgec[1], edgec[2], rgb2[0], rgb2[1], rgb2[2]))
701
716
/* Compute adjusted edge count for channels we're remeasuring, */
718
733
if (edgec[0] > 1 || edgec[1] > 1 || edgec[2] > 1) {
719
734
double rgb3[3]; /* 2nd RGB Readings */
721
if ((ev = huey_take_raw_measurement_2(p, edgec, rgb3)) != inst_ok)
736
if ((ev = huey_period_measure(p, edgec, rgb3)) != inst_ok)
724
DBG(("Raw subsequent2 ecount %d %d %d RGB = %f %f %f\n",
739
DBG((dbgo,"Raw subsequent2 ecount %d %d %d RGB = %f %f %f\n",
725
740
edgec[0], edgec[1], edgec[2], rgb3[0], rgb3[1], rgb3[2]))
727
742
/* Average readings if we repeated a measurement with the same threshold */
738
753
for (i = 0; i < 3; i++) {
740
755
rgb[i] = ((double)edgec[i])/(rgb2[i] * 2.0 * p->clk_prd);
741
DBG(("%d after scale = %f\n",i,rgb[i]))
756
DBG((dbgo,"%d after scale = %f\n",i,rgb[i]))
743
758
rgb[i] -= p->dark_cal[i]; /* Subtract black level */
744
DBG(("%d after sub black = %f\n",i,rgb[i]))
759
DBG((dbgo,"%d after sub black = %f\n",i,rgb[i]))
746
761
if (rgb[i] < 0.0001)
748
DBG(("%d after limit min = %f\n",i,rgb[i]))
763
DBG((dbgo,"%d after limit min = %f\n",i,rgb[i]))
753
DBG(("Cooked RGB = %f %f %f\n",rgb[0],rgb[1],rgb[2]))
768
DBG((dbgo,"Cooked RGB = %f %f %f\n",rgb[0],rgb[1],rgb[2]))
801
816
if (p->inited == 0)
802
817
return huey_interp_code((inst *)p, HUEY_NOT_INITED);
804
DBG(("take_amb_measurement_2 called with crtm = %d\n",crtm));
819
DBG((dbgo,"take_amb_measurement_2 called with crtm = %d\n",crtm));
806
821
/* First param is always 3, second is sync mode */
807
822
if ((ev = huey_take_amb_measurement_1(p, 3, crtm ? 2 : 0, amb, &rb)) != inst_ok)
809
DBG(("Raw ambient = %f\n",*amb))
824
DBG((dbgo,"Raw ambient = %f\n",*amb))
872
887
XYZ[i] *= CALFACTOR; /* Times magic scale factor */
890
/* Apply the colorimeter correction matrix */
891
icmMulBy3x3(XYZ, p->ccmat, XYZ);
875
DBG(("returning XYZ = %f %f %f\n",XYZ[0],XYZ[1],XYZ[2]))
893
DBG((dbgo,"returning XYZ = %f %f %f\n",XYZ[0],XYZ[1],XYZ[2]))
932
950
/* Serial number */
933
951
if ((ev = huey_rdreg_word(p, &p->ser_no, 0) ) != inst_ok)
935
DBG(("serial number = %d\n",p->ser_no))
953
DBG((dbgo,"serial number = %d\n",p->ser_no))
938
956
/* LCD/user calibration values */
939
957
for (i = 0; i < 9; i++) {
940
958
if ((ev = huey_rdreg_float(p, &p->LCD_cal[i], 4 + 4 * i) ) != inst_ok)
942
DBG(("LCD/user cal[%d] = %f\n",i,p->LCD_cal[i]))
960
DBG((dbgo,"LCD/user cal[%d] = %f\n",i,p->LCD_cal[i]))
944
962
/* LCD/user calibration time */
945
963
if ((ev = huey_rdreg_word(p, &p->LCD_caltime, 50) ) != inst_ok)
947
DBG(("LCD/user calibration time = 0x%x = %s\n",p->LCD_caltime, ctime(&p->LCD_caltime)))
965
DBG((dbgo,"LCD/user calibration time = 0x%x = %s\n",p->LCD_caltime, ctime_32(&p->LCD_caltime)))
950
968
/* CRT/factory calibration values */
951
969
for (i = 0; i < 9; i++) {
952
970
if ((ev = huey_rdreg_float(p, &p->CRT_cal[i], 54 + 4 * i) ) != inst_ok)
954
DBG(("CRT/factory cal[%d] = %f\n",i,p->CRT_cal[i]))
972
DBG((dbgo,"CRT/factory cal[%d] = %f\n",i,p->CRT_cal[i]))
956
974
/* CRT/factory calibration flag */
957
975
if ((ev = huey_rdreg_word(p, &p->CRT_caltime, 90) ) != inst_ok)
959
DBG(("CRT/factory flag = 0x%x = %s\n",p->CRT_caltime, ctime(&p->CRT_caltime)))
977
DBG((dbgo,"CRT/factory flag = 0x%x = %s\n",p->CRT_caltime, ctime_32(&p->CRT_caltime)))
962
980
/* Hard coded in Huey */
963
981
p->clk_prd = 1e-6;
964
DBG(("Clock period = %f\n",p->clk_prd))
982
DBG((dbgo,"Clock period = %f\n",p->clk_prd))
966
984
/* Dark current calibration values */
967
985
for (i = 0; i < 3; i++) {
971
989
p->dark_cal[i] = 0.0;
973
DBG(("darkcal[%d] = %f\n",i,p->dark_cal[i]))
991
DBG((dbgo,"darkcal[%d] = %f\n",i,p->dark_cal[i]))
976
994
/* Ambient darkcurrent calibration value ? */
989
1007
p->unlk_string[i] = (char)vv;
991
1009
p->unlk_string[i] = '\000';
992
DBG(("unlock string = '%s'\n",p->unlk_string))
1010
DBG((dbgo,"unlock string = '%s'\n",p->unlk_string))
994
1012
/* Read the integration time */
995
1013
if ((ev = huey_rd_int_time(p, &p->int_clocks) ) != inst_ok)
997
DBG(("Integration time = %d\n",p->int_clocks))
1015
DBG((dbgo,"Integration time = %d\n",p->int_clocks))
999
1017
if (p->debug) fprintf(stderr,"huey: all registers read OK\n");
1023
1041
/* clk_prd inversion */
1024
1042
p->clk_freq = 1.0/p->clk_prd;
1025
DBG(("clk_freq = %f\n",p->clk_freq))
1043
DBG((dbgo,"clk_freq = %f\n",p->clk_freq))
1027
1045
/* Set some defaults */
1028
1046
p->sampno = 100; /* Minimum sampling count */
1055
1075
if (p->debug) fprintf(stderr,"huey: About to init HID\n");
1057
1077
/* Set config, interface */
1058
p->icom->set_hid_port(p->icom, port, icomuf_none);
1078
p->icom->set_hid_port(p->icom, port, icomuf_none, retries, pnames);
1060
1080
if (p->icom->vid == 0x0765 && p->icom->pid == 0x5001) {
1061
1081
if (p->debug) fprintf(stderr,"huey: Lenovo version\n");
1168
1186
int user_trig = 0;
1169
1187
int rv = inst_protocol_error;
1190
return inst_no_coms;
1192
return inst_no_init;
1171
1194
if (p->trig == inst_opt_trig_keyb) {
1173
1196
if ((se = icoms_poll_user(p->icom, 1)) != ICOM_TRIG) {
1174
1197
/* Abort, term or command */
1175
return huey_interp_code((inst *)p, icoms2huey_err(se));
1198
return huey_interp_code((inst *)p, icoms2huey_err(se, 1));
1178
1201
if (p->trig_return)
1457
inst_disptypesel huey_disptypesel[3] = {
1461
"Huey: CRT display",
1467
"Huey: LCD display",
1478
/* Get mode and option details */
1479
static inst_code huey_get_opt_details(
1481
inst_optdet_type m, /* Requested option detail type */
1482
...) { /* Status parameters */
1483
huey *p = (huey *)pp;
1484
inst_code rv = inst_ok;
1486
if (m == inst_optdet_disptypesel) {
1489
inst_disptypesel **psels;
1492
pnsels = va_arg(args, int *);
1493
psels = va_arg(args, inst_disptypesel **);
1497
*psels = huey_disptypesel;
1502
return inst_unsupported;
1422
1505
/* Set device measurement mode */
1423
1506
inst_code huey_set_mode(inst *pp, inst_mode m)
1425
1508
huey *p = (huey *)pp;
1426
1509
inst_mode mm; /* Measurement mode */
1512
return inst_no_coms;
1514
return inst_no_init;
1428
1516
/* The measurement mode portion of the mode */
1429
1517
mm = m & inst_mode_measurement_mask;
1453
1541
huey *p = (huey *)pp;
1454
1542
inst_code ev = inst_ok;
1456
/* Select CRT/LCD */
1457
if (m == inst_opt_disp_crt) {
1461
} else if (m == inst_opt_disp_lcd) {
1545
return inst_no_coms;
1547
return inst_no_init;
1549
/* Set the display type */
1550
if (m == inst_opt_disp_type) {
1555
ix = va_arg(args, int);
1562
} else if (ix == 2) {
1567
return inst_unsupported;
1467
1571
/* Record the trigger mode */
1468
1572
if (m == inst_opt_trig_prog
1469
1573
|| m == inst_opt_trig_keyb) {
1513
1617
/* Constructor */
1514
extern huey *new_huey(icoms *icom, int debug, int verb)
1618
extern huey *new_huey(icoms *icom, instType itype, int debug, int verb)
1517
1621
if ((p = (huey *)calloc(sizeof(huey),1)) == NULL)
1531
1635
p->init_inst = huey_init_inst;
1532
1636
p->capabilities = huey_capabilities;
1533
1637
p->capabilities2 = huey_capabilities2;
1638
p->get_opt_details = huey_get_opt_details;
1534
1639
p->set_mode = huey_set_mode;
1535
1640
p->set_opt_mode = huey_set_opt_mode;
1536
1641
p->read_sample = huey_read_sample;