~ubuntu-branches/ubuntu/saucy/argyll/saucy

« back to all changes in this revision

Viewing changes to spectro/i1disp.c

  • Committer: Package Import Robot
  • Author(s): Christian Marillat
  • Date: 2012-04-25 07:46:07 UTC
  • mfrom: (1.2.2) (13.1.15 sid)
  • Revision ID: package-import@ubuntu.com-20120425074607-yjqadetw8kum9skc
Tags: 1.4.0-4
Should Build-Depends on libusb-dev (Closes: #670329).

Show diffs side-by-side

added added

removed removed

Lines of Context:
43
43
#include "copyright.h"
44
44
#include "aconfig.h"
45
45
#include "numlib.h"
 
46
#else   /* !SALONEINSTLIB */
 
47
#include "sa_config.h"
 
48
#include "numsup.h"
46
49
#endif /* !SALONEINSTLIB */
47
50
#include "xspect.h"
48
51
#include "insttypes.h"
95
98
/* A = string (5 bytes total max) , - = none */
96
99
typedef enum {
97
100
    i1d_status       = 0x00,            /* -:A    Get status string */
98
 
    i1d_rd_red       = 0x01,            /* -:W    Read the red channel */
99
 
    i1d_rd_green     = 0x02,            /* -:W    Read the green channel */
100
 
    i1d_rd_blue      = 0x03,            /* -:W    Read the blue channel */
101
 
    i1d_getmeas_p    = 0x04,            /* -:W    Read the measure period */
 
101
    i1d_rd_red       = 0x01,            /* -:W    Read the red channel clk count (and trig ?) */
 
102
    i1d_rd_green     = 0x02,            /* -:W    Read the green channel clk count */
 
103
    i1d_rd_blue      = 0x03,            /* -:W    Read the blue channel clk count */
 
104
    i1d_getmeas_p    = 0x04,            /* -:W    Read the measure refresh period */
102
105
    i1d_setintgt     = 0x05,            /* W:-    Set the integration time */
103
106
    i1d_getintgt     = 0x06,            /* -:W    Get the integration time */
104
107
    i1d_wrreg        = 0x07,            /* BB:-   Write a register value */
105
108
    i1d_rdreg        = 0x08,            /* B:B    Read a register value */
106
 
    id1_getmeas_p2   = 0x09,            /* -:W    Read the measure period (finer resolution ?) */
107
 
    i1d_m_red_p      = 0x0a,            /* B:W    Measure the red period */
108
 
    i1d_m_green_p    = 0x0b,            /* B:W    Measure the green period */
109
 
    i1d_m_blue_p     = 0x0c,            /* B:W    Measure the blue period */
110
 
    i1d_m_rgb_p      = 0x0d,            /* BBB:W  Measure the RGB period */
 
109
    i1d_getmeas_p2   = 0x09,            /* -:W    Read the measure refresh period (finer ?) */
 
110
    i1d_m_red_p      = 0x0a,            /* B:W    Measure the red period for given edge count */
 
111
    i1d_m_green_p    = 0x0b,            /* B:W    Measure the green period for given edge count */
 
112
    i1d_m_blue_p     = 0x0c,            /* B:W    Measure the blue period for given edge count */
 
113
    i1d_m_rgb_p      = 0x0d,            /* BBB:W  Measure the RGB period for given edge count */
111
114
    i1d_unlock       = 0x0e,            /* BBBB:- Unlock the interface */
112
115
 
113
 
    i1d_m_red_p2     = 0x10,            /* S:W    Measure the red period (16 bit ?) */
114
 
    i1d_m_green_p2   = 0x11,            /* S:W    Measure the green period (16 bit ?) */
115
 
    i1d_m_blue_p2    = 0x12,            /* S:W    Measure the blue period (16 bit ?) */
116
 
                                                                        /* S = ??? */
 
116
    i1d_m_red_p2     = 0x10,            /* S:W    Measure the red period (16 bit) */
 
117
    i1d_m_green_p2   = 0x11,            /* S:W    Measure the green period (16 bit) */
 
118
    i1d_m_blue_p2    = 0x12,            /* S:W    Measure the blue period (16 bit) */
 
119
                                                                        /* S = edge count */
117
120
 
118
 
    i1d_m_red_2      = 0x13,            /* B:W    Measure the red channel (16 bit ?) */
 
121
    i1d_m_red_2      = 0x13,            /* B:W    Measure the red channel (16 bit) */
119
122
                                                                        /* B = sync mode, typically 1 */
120
123
 
121
124
    i1d_setmedges2   = 0x14,            /* SB:-   Set number of edges used for measurment 16 bit */
123
126
    i1d_getmedges2   = 0x15,            /* B:S    Get number of edges used for measurment 16 bit */
124
127
                                                                        /* B = channel */
125
128
 
126
 
    i1d_m_rgb_edge_2 = 0x16,            /* -:W    Measure RGB Edge (16 bit ?) */
 
129
    i1d_m_rgb_edge_2 = 0x16,            /* -:W    Measure RGB Edge (16 bit) */
127
130
 
128
131
    i1d_set_pll_p    = 0x11,            /* SS:-   Set PLL period */
129
132
    i1d_get_pll_p    = 0x12,            /* -:W    Get PLL period */
130
133
 
131
 
    i1d_m_rgb_edge_3 = 0x10,            /* BBBB:W Measure RGB Edge */
132
 
                                                                        /* BBBB = ??? */
 
134
    i1d_m_rgb_edge_3 = 0x10,            /* BBBB:W Measure RGB Edge & return red. */
 
135
                                                                        /* BBBB = edge counts ??? */
133
136
    i1d_g_green_3    = 0x11,            /* -:W    Get green data */
134
137
    i1d_g_blue_3     = 0x12,            /* -:W    Get blue data */
135
138
 
160
163
        int value;                              /* 16 bit value (USB wValue, sent little endian) */
161
164
        int index;                              /* 16 bit index (USB wIndex, sent little endian) */
162
165
        int rwsize;                             /* 16 bit data size (USB wLength, send little endian) */ 
163
 
        int rcc;                                /* Return cc code from instruction */
 
166
        int rcc = 0;                    /* Return cc code from instruction */
164
167
        int i, tsize;
165
168
        unsigned char buf[8];   /* 8 bytes to read */
166
169
        int se, ua = 0, rv = inst_ok;
203
206
                                                fprintf(dbgo,"\ni1disp: Timeout %f sec, Took %f sec.\n",to, (msec_time() - smsec)/1000.0);
204
207
 
205
208
                                }
 
209
                                p->last_com_err = se;
206
210
                                p->icom->debug = isdeb;
207
211
                                return i1disp_interp_code((inst *)p, I1DISP_COMS_FAIL);
208
212
                        }
310
314
                if (addr < 0 || addr > 159)
311
315
                        return i1disp_interp_code((inst *)p, I1DISP_BAD_REG_ADDRESS);
312
316
        }
313
 
        c = addr;  
 
317
        c = (unsigned char)addr;  
314
318
 
315
319
        /* Read a byte */
316
320
        if ((ev = i1disp_command(p, i1d_rdreg, &c, 1,
427
431
        if (cval == inv)        /* No need to write */
428
432
                return inst_ok;
429
433
 
430
 
        ibuf[0] = addr;  
431
 
        ibuf[1] = inv;  
 
434
        ibuf[0] = (unsigned char)addr;  
 
435
        ibuf[1] = (unsigned char)inv;  
432
436
 
433
437
        /* Write a byte */
434
438
        if ((ev = i1disp_command(p, i1d_wrreg, ibuf, 2,
538
542
        return inst_ok;
539
543
}
540
544
 
541
 
/* Read the measurement period */
 
545
/* Read the refresh period */
542
546
static inst_code
543
 
i1disp_rd_meas_period(
 
547
i1disp_rd_meas_ref_period(
544
548
        i1disp *p,                              /* Object */
545
549
        int *outp                               /* Where to write value */
546
550
) {
548
552
        int rsize;
549
553
        inst_code ev;
550
554
 
551
 
        if ((ev = i1disp_command(p, id1_getmeas_p2, NULL, 0,
 
555
        if ((ev = i1disp_command(p, i1d_getmeas_p2, NULL, 0,
552
556
                         buf, 8, &rsize, 1.5)) != inst_ok)
553
557
                return ev;
554
558
        
562
566
 
563
567
/* - - - - - - - - - - - - - - - - - - - - - - - - */
564
568
 
565
 
/* Take a raw RGB measurement from the device for an i1d1 */
566
 
/* The raw measurement seems something like an integration time */
567
 
/* in clocks, to reach the given threshold (ie. dual slope integral A/D ?). */
 
569
/* Take a raw RGB period measurement from the device for an i1d1. */
 
570
/* The time taken to count the given number of L2F clock edges (+ve & -ve) */
 
571
/* is measured in clk clk_freq counts. */ 
568
572
static inst_code
569
 
i1disp_take_raw_measurement_1(
 
573
i1d1_period_measure(
570
574
        i1disp *p,                              /* Object */
571
 
        int intthr[3],                  /* Threshold 1..255 for each channel ?? */
572
 
        double rgb[3]                   /* Return the RGB A/D values */
 
575
        int edgec[3],                   /* Number of clock edges to count */
 
576
        double rgb[3]                   /* Return the number of clk's */
573
577
) {
574
578
        int i;
575
579
        unsigned char ibuf[16];
577
581
        int rsize;
578
582
        inst_code ev;
579
583
 
580
 
        /* Sanity check the threshold */
 
584
        /* Sanity check the number of edges */
581
585
        for (i = 0; i < 3; i++) {
582
 
                if (intthr[i] < 1 || intthr[i] > 255)
 
586
                if (edgec[i] < 1 || edgec[i] > 255)
583
587
                        return i1disp_interp_code((inst *)p, I1DISP_BAD_INT_THRESH);
584
 
                ibuf[i] = (char)intthr[i];
 
588
                ibuf[i] = (char)edgec[i];
585
589
        }
586
590
 
587
591
        /* Do the measurement, and return the Red value */
611
615
        return inst_ok;
612
616
}
613
617
 
614
 
/* Take a cooked measurement from the device for the i1d1 */
 
618
/* Take a cooked period measurement from the device for the i1d1 */
 
619
/* and return the frequency for each sensor. */
615
620
static inst_code
616
 
i1disp_take_measurement_1(
 
621
i1d1_take_measurement(
617
622
        i1disp *p,                              /* Object */
618
623
        int cal,                                /* nz if black is not to be subtracted */
619
 
        double rgb[3]                   /* Return the rgb values */
 
624
        double rgb[3]                   /* Return the rgb frequency values */
620
625
) {
621
 
        int i, j;
622
 
        int intthr[3];          /* Integration times 1..255 for each channel */
 
626
        int i;
 
627
        int edgec[3];           /* Edge count 1..255 for each channel */
623
628
        inst_code ev;
624
629
 
625
630
        if (p->inited == 0)
628
633
        if (p->dtype != 0)
629
634
                return i1disp_interp_code((inst *)p, I1DISP_WRONG_DEVICE);
630
635
 
631
 
        /* Do an initial measurement with minimum integration threshold of 1 */
632
 
        intthr[0] = intthr[1] = intthr[2] = 1;
 
636
        /* Do an initial measurement with minimum edge count of 1 */
 
637
        edgec[0] = edgec[1] = edgec[2] = 1;
633
638
 
634
 
        if ((ev = i1disp_take_raw_measurement_1(p, intthr, rgb)) != inst_ok)
 
639
        if ((ev = i1d1_period_measure(p, edgec, rgb)) != inst_ok)
635
640
                return ev;
636
641
 
637
642
        DBG((dbgo, "Initial RGB = %f %f %f\n",rgb[0],rgb[1],rgb[2]))
638
643
 
639
 
        /* Compute adjusted integration threshold, aiming */
640
 
        /* for count values of clk_freq (~1e6). */
 
644
        /* Compute adjusted edge count, aiming */
 
645
        /* for count values of clk_freq = 1 second (~1e6). */
641
646
        for (i = 0; i < 3; i++) {
642
647
                double ns;
643
648
                if (p->clk_freq > ((255.0 - 0.5) * rgb[i]))
647
652
                        if (ns < 1.0)
648
653
                                ns = 1.0;
649
654
                }
650
 
                intthr[i] = (int)ns;
 
655
                edgec[i] = (int)ns;
651
656
        }
652
657
 
653
 
        /* If we compute a different threshold, read again */
654
 
        if (intthr[0] > 1 || intthr[1] > 1 || intthr[2] > 1) {
 
658
        /* Only if we compute a different edge count, read again */
 
659
        if (edgec[0] > 1 || edgec[1] > 1 || edgec[2] > 1) {
655
660
                double rgb2[3];         /* 2nd RGB Readings */
656
661
 
657
 
                if ((ev = i1disp_take_raw_measurement_1(p, intthr, rgb2)) != inst_ok)
 
662
                if ((ev = i1d1_period_measure(p, edgec, rgb2)) != inst_ok)
658
663
                        return ev;
659
664
 
660
 
                /* Average readings if we repeated a measurement with the same threshold */
 
665
                /* Average readings if we repeated a measurement with the same edge count */
661
666
                /* (Minor advantage, but may as well use it) */
662
667
                for (i = 0; i < 3; i++) {
663
 
                        if (intthr[i] == 1)
 
668
                        if (edgec[i] == 1)
664
669
                                rgb[i] = 0.5 * (rgb[i] + rgb2[i]);
665
670
                        else
666
671
                                rgb[i] = rgb2[i];
667
672
                }
668
673
        }
669
674
 
670
 
        DBG((dbgo, "scaled %d %d %d gives RGB = %f %f %f\n", intthr[0],intthr[1],intthr[2], rgb[0],rgb[1],rgb[2]))
 
675
        DBG((dbgo, "scaled %d %d %d gives RGB = %f %f %f\n", edgec[0],edgec[1],edgec[2], rgb[0],rgb[1],rgb[2]))
671
676
 
672
 
        /* Compute adjusted readings */
673
 
        /* We need to invert the count to give a light level, and */
674
 
        /* multiply by the integration threshold, */
675
 
        /* (divide by the clock period to give integration time in seconds) */
 
677
        /* Compute adjusted readings as a frequency. */
 
678
        /* We need to divide the number of edges/2 by the period in seconds */
676
679
        for (i = 0; i < 3; i++) {
677
 
                rgb[i] = (p->rgbadj2[i] * (double)intthr[i])/(rgb[i] * 2.0 * p->clk_prd);
678
 
                DBG((dbgo, "%d after scale = %f\n",i,rgb[i]))
 
680
                rgb[i] = (p->rgbadj[i] * 0.5 * (double)edgec[i] * p->clk_freq)/rgb[i];
 
681
                DBG((dbgo, "%d sensor frequency = %f\n",i,rgb[i]))
679
682
 
680
683
                /* If we're not calibrating the black */
681
684
                if (cal == 0) {
694
697
 
695
698
/* . . . . . . . . . . . . . . . . . . . . . . . . */
696
699
 
697
 
/* Take a raw initial measurement from the device for an i1d2 */
 
700
/* Take a fixed period frequency measurement from the device for an i1d2. */
 
701
/* This measures edge count over the set integration period. */
 
702
 
 
703
/* Take a raw measurement using a given integration time. */
 
704
/* The measureent is the count of (both) edges from the L2V */
 
705
/* over the integration time */
698
706
static inst_code
699
 
i1disp_take_first_raw_measurement_2(
 
707
i1d2_freq_measure(
700
708
        i1disp *p,                              /* Object */
701
 
        double rgb[3]                   /* Return the RGB values */
 
709
        double *inttime,                /* Integration time in seconds. (Return clock rounded) */
 
710
        double rgb[3]                   /* Return the RGB edge count values */
702
711
) {
703
 
        int i;
704
712
        unsigned char ibuf[16];
705
713
        unsigned char obuf[16];
 
714
        int intclks;
706
715
        int rsize;
707
716
        inst_code ev;
708
717
 
 
718
        if (*inttime > 20.0)            /* Hmm */
 
719
                *inttime = 20.0;
 
720
 
 
721
        intclks = (int)(*inttime * p->iclk_freq + 0.5);
 
722
        *inttime = (double)intclks / p->iclk_freq;
 
723
        if (intclks != p->int_clocks) {
 
724
                if ((ev = i1disp_wr_int_time(p, intclks)) != inst_ok)
 
725
                        return ev;
 
726
                if ((ev = i1disp_rd_int_time(p, &intclks) ) != inst_ok)
 
727
                        return ev;
 
728
                p->int_clocks = intclks;
 
729
                *inttime = (double)p->int_clocks/p->iclk_freq;
 
730
        }
 
731
 
709
732
        /* Do the measurement, and return the Red value */
710
733
        ibuf[0] = 1;            /* Sync mode 1 */
711
734
        if ((ev = i1disp_command(p, i1d_m_red_2, ibuf, 1,
712
 
                         obuf, 8, &rsize, p->samptime + 1.0)) != inst_ok)
 
735
                         obuf, 8, &rsize, p->inttime + 1.0)) != inst_ok)
713
736
                return ev;
714
737
        if (rsize != 5)
715
738
                return i1disp_interp_code((inst *)p, I1DISP_UNEXPECTED_RET_SIZE);
734
757
        return inst_ok;
735
758
}
736
759
 
737
 
/* Take a raw initial subsequent mesurement from the device for an i1d2 */
 
760
static inst_code i1disp_init_inst(inst *pp);
 
761
 
 
762
/* Take a raw measurement that returns the number of clocks */
 
763
/* between and initial edge and edgec[] subsequent edges of the L2F. */
 
764
/* Both edges are counted. */ 
738
765
static inst_code
739
 
i1disp_take_raw_measurement_2(
 
766
i1d2_period_measure(
740
767
        i1disp *p,                      /* Object */
741
768
        int edgec[3],           /* Measurement edge count for each channel */
742
 
        double rgb[3]           /* Return the RGB values */
 
769
        double rgb[3]           /* Return the RGB clock count values */
743
770
) {
744
 
        int i, tries = 2;
 
771
        int i;
745
772
        unsigned char ibuf[16];
746
773
        unsigned char obuf[16];
747
774
        int rsize;
750
777
        /* Set the edge count */
751
778
        for (i = 0; i < 3; i++) {
752
779
                short2buf(ibuf, edgec[i]);      /* Edge count */
753
 
                ibuf[2] = i;                            /* Channel number */
 
780
                ibuf[2] = (unsigned char)i;     /* Channel number */
754
781
                if ((ev = i1disp_command(p, i1d_setmedges2, ibuf, 3,
755
 
                                 obuf, 8, &rsize, p->samptime + 1.0)) != inst_ok)
 
782
                                 obuf, 8, &rsize, 1.0)) != inst_ok)
756
783
                        return ev;
757
784
        }
758
785
 
759
 
//      for (i = 0; i < 2; i++) {
760
786
        /* Do the measurement, and return the Red value */
761
787
        if ((ev = i1disp_command(p, i1d_m_rgb_edge_2, ibuf, 0,
762
 
                         obuf, 8, &rsize, 120.0)) != inst_ok)
 
788
                         obuf, 8, &rsize, 120.0)) != inst_ok) {
763
789
                return ev;
 
790
        }
764
791
        if (rsize != 5)
765
792
                return i1disp_interp_code((inst *)p, I1DISP_UNEXPECTED_RET_SIZE);
766
793
        rgb[0] = (double)buf2int(obuf);
784
811
        return inst_ok;
785
812
}
786
813
 
787
 
#define ME 1
 
814
#define ME 1            /* One edge initially (should this be 2 ?) */
 
815
 
 
816
#ifndef NEVER
 
817
 
 
818
/* ### Quick and precise for low levels, but subject to long */
 
819
/* ### delays if the light level drops during measurement, and */
 
820
/* ### may be less accurate at low levels due to dark noise */
788
821
 
789
822
/* Take a cooked measurement from the device for the i1d2 */
790
823
static inst_code
791
 
i1disp_take_measurement_2(
 
824
i1d2_take_measurement(
792
825
        i1disp *p,                              /* Object */
793
 
        int crtm,                               /* nz if crt mode */
 
826
        int crtm,                               /* Measure in crt mode flag */
794
827
        double rgb[3]                   /* Return the rgb values */
795
828
) {
796
 
        int i, j;
 
829
        int i;
 
830
        double rmeas[3];                        /* Raw measurement */
797
831
        int edgec[3] = {ME,ME,ME};      /* Measurement edge count for each channel */
798
 
        int rem[3] = {1,1,1};   /* remeasure flags */
 
832
        int cdgec[3] = {ME,ME,ME};      /* CRT computed edge count for re-measure */
 
833
        int mask = 0x0;                         /* Period measure mask */
799
834
        inst_code ev;
800
835
 
801
836
        if (p->inited == 0)
804
839
        if (p->dtype == 0)
805
840
                return i1disp_interp_code((inst *)p, I1DISP_WRONG_DEVICE);
806
841
 
807
 
        DBG((dbgo, "take_measurement_2 called with crtm = %d\n",crtm));
 
842
        DBG((dbgo, "i1d2_take_measurement called with crtm = %d\n",crtm));
808
843
 
809
 
        /* Do CRT frequency calibration/set integration time if needed */
810
 
        if (p->itset == 0) {
 
844
        /* Do refresh period measurement */
 
845
        if (crtm && p->rrset == 0) {
811
846
                if ((ev = i1disp_do_fcal_setit(p)) != inst_ok)
812
847
                        return ev;
 
848
                p->rrset = 1;
 
849
 
 
850
                /* Quantize the sample time */
 
851
                if (p->refperiod > 0.0) {
 
852
                        int n;
 
853
                        n = (int)ceil(p->dinttime/p->refperiod);
 
854
                        p->inttime = n * p->refperiod;
 
855
                        if (p->debug) fprintf(stderr,"i1disp: integration time quantize to %f secs\n",p->inttime);
 
856
                } else {
 
857
                        p->inttime = p->dinttime;       
 
858
                        if (p->debug) fprintf(stderr,"i1disp: integration time set to %f secs\n",p->inttime);
 
859
                }
813
860
        }
814
861
 
815
 
        /* For CRT mode, do an initial set of syncromized measurements */
816
 
        if (crtm) {
817
 
 
818
 
                if ((ev = i1disp_take_first_raw_measurement_2(p, rgb)) != inst_ok)
 
862
// Do a frequency measurement first, to reduces chances of a light change causing delays.
 
863
// This makes LCD same as CRT as far as quantization errors in high level readings.
 
864
//      if (crtm) {
 
865
                /* Do an initial fixed integration time frequency measurement. */
 
866
                DBG((dbgo,"Doing fixed period frequency measurement over %f secs\n",p->inttime))
 
867
        
 
868
                if ((ev = i1d2_freq_measure(p, &p->inttime, rmeas)) != inst_ok)
819
869
                        return ev;
820
 
 
821
 
                DBG((dbgo, "Raw initial CRT RGB = %f %f %f\n",rgb[0],rgb[1],rgb[2]))
822
 
 
 
870
        
 
871
                for (i = 0; i < 3; i++)
 
872
                        rgb[i] = p->rgbadj[i] * 0.5 * rmeas[i]/p->inttime;
 
873
        
 
874
                DBG((dbgo,"Got %f %f %f raw, %f %f %f Hz\n",
 
875
                rmeas[0], rmeas[1], rmeas[2], rgb[0], rgb[1], rgb[2]))
 
876
        
823
877
                /* Decide whether any channels need re-measuring, */
824
 
                /* and computed cooked values. Threshold is typically 75 */
 
878
                /* and computed cooked values. Threshold is a count of 75 */
825
879
                for (i = 0; i < 3; i++) {
826
 
                        rem[i] = (rgb[i] <= (0.75 * (double)p->sampno)) ? 1 : 0;
827
 
                        rgb[i] = 0.5 * rgb[i] * p->rgbadj1[i]/(double)p->int_clocks;
 
880
                        if (rmeas[i] <= 75.0) {
 
881
                                mask |= (1 << i);               /* Yes */
 
882
                                if (rmeas[i] >= 10.0) { /* Compute target edges */
 
883
                                        cdgec[i] = (int)(2.0 * rgb[i] * p->inttime + 0.5); 
 
884
                                        if (cdgec[i] > 2000)
 
885
                                                cdgec[i] = 2000;
 
886
                                        else if (cdgec[i] < ME)
 
887
                                                cdgec[i] = ME;
 
888
                                }
 
889
                        }
828
890
                }
829
 
                DBG((dbgo,"Re-measure flags = %d %d %d\n",rem[0],rem[1],rem[2]))
830
 
        }
 
891
//      } else {
 
892
//              mask = 0x7;
 
893
//      }
 
894
        DBG((dbgo,"Re-measure mask = 0x%x\n",mask))
 
895
        DBG((dbgo,"cdgec = %d %d %d\n",cdgec[0],cdgec[1],cdgec[2]))
831
896
 
832
897
        /* If any need re-measuring */
833
 
        if (rem[0] || rem[1] || rem[2]) {
834
 
                double rgb2[3];
835
 
 
836
 
                /* Do a first or second set of measurements */
837
 
                if ((ev = i1disp_take_raw_measurement_2(p, edgec, rgb2)) != inst_ok)
838
 
                        return ev;
839
 
                DBG((dbgo,"Raw initial/subsequent ecount %d %d %d RGB = %f %f %f\n",
840
 
                     edgec[0], edgec[1], edgec[2], rgb2[0], rgb2[1], rgb2[2]))
841
 
 
842
 
                /* Compute adjusted edge count for channels we're remeasuring, */
843
 
                /* aiming for count values of clk_freq (~1e6). */
844
 
                for (i = 0; i < 3; i++) {
845
 
                        double ns;
846
 
                        if (rem[i]) {
847
 
                                if (p->clk_freq > ((2000.0 - 0.5) * rgb2[i]))
848
 
                                        ns = 2000.0;                    /* Maximum edge count */
849
 
                                else {
850
 
                                        ns = floor(p->clk_freq/rgb2[i]) + 0.5;
851
 
                                        if (ns < ME)                    /* Minimum edge count */
852
 
                                                ns = ME;
853
 
                                }
854
 
                                edgec[i] = (int)ns;
855
 
                        }
856
 
                }
857
 
        
858
 
                /* If we compute a different edge count, read again */
859
 
                if (edgec[0] > ME || edgec[1] > ME || edgec[2] > ME) {
860
 
                        double rgb3[3];         /* 2nd RGB Readings */
861
 
        
862
 
                        if ((ev = i1disp_take_raw_measurement_2(p, edgec, rgb3)) != inst_ok)
863
 
                                return ev;
864
 
        
865
 
                        DBG((dbgo,"Raw subsequent2 ecount %d %d %d RGB = %f %f %f\n",
866
 
                             edgec[0], edgec[1], edgec[2], rgb3[0], rgb3[1], rgb3[2]))
867
 
 
868
 
                        /* Average readings if we repeated a measurement with the same threshold */
869
 
                        /* (Minor advantage, but may as well use it) */
870
 
                        for (i = 0; i < 3; i++) {
871
 
                                if (edgec[i] == 1)
872
 
                                        rgb2[i] = 0.5 * (rgb2[i] + rgb3[i]);
873
 
                                else
874
 
                                        rgb2[i] = rgb3[i];
875
 
                        }
876
 
                }
877
 
 
878
 
                /* Compute adjusted readings, ovewritting initial cooked values */
879
 
                for (i = 0; i < 3; i++) {
880
 
                        if (rem[i]) {
881
 
                                rgb[i] = (p->rgbadj2[i] * (double)edgec[i])/(rgb2[i] * 2.0 * p->clk_prd);
882
 
                                DBG((dbgo,"%d after scale = %f\n",i,rgb[i]))
883
 
                
884
 
                                rgb[i] -= p->reg103_F[i];               /* Subtract black level */
885
 
                                DBG((dbgo,"%d after sub black = %f\n",i,rgb[i]))
886
 
                
887
 
                                if (rgb[i] < 0.0001)
888
 
                                        rgb[i] = 0.0001;
889
 
                                DBG((dbgo,"%d after limit min = %f\n",i,rgb[i]))
890
 
                        }
891
 
                }
892
 
        }
893
 
 
894
 
        DBG((dbgo,"Cooked RGB = %f %f %f\n",rgb[0],rgb[1],rgb[2]))
895
 
        
896
 
        return inst_ok;
897
 
}
 
898
        if (mask != 0) {
 
899
 
 
900
                /* See if we need to compute a target edge count */
 
901
                for (i = 0; i < 3; i++) {
 
902
                        if ((mask & (1 << i)) && cdgec[i] == ME)
 
903
                                break;
 
904
                }
 
905
 
 
906
                /* Yes we do */
 
907
                if (i < 3) {
 
908
 
 
909
                        DBG((dbgo,"Doing 1st period pre-measurement mask 0x%x, edgec %d %d %d\n",
 
910
                        mask, edgec[0], edgec[1], edgec[2]))
 
911
 
 
912
                        /* Do an initial measurement of 1 edge to estimate the */
 
913
                        /* number of edges needed for the whole integration time. */
 
914
                        if ((ev = i1d2_period_measure(p, edgec, rmeas)) != inst_ok)
 
915
                                return ev;
 
916
 
 
917
                        DBG((dbgo,"Got %f %f %f raw %f %f %f Hz\n",
 
918
                        rmeas[0], rmeas[1], rmeas[2],
 
919
                        (p->rgbadj[0] * 0.5 * (double)edgec[0] * p->clk_freq)/rmeas[0],
 
920
                        (p->rgbadj[1] * 0.5 * (double)edgec[1] * p->clk_freq)/rmeas[1],
 
921
                        (p->rgbadj[2] * 0.5 * (double)edgec[2] * p->clk_freq)/rmeas[2]))
 
922
 
 
923
                        /* Compute adjusted edge count for channels we're remeasuring, */
 
924
                        /* aiming for a values of int_clocks. */
 
925
                        for (i = 0; i < 3; i++) {
 
926
                                double ns;
 
927
                                if ((mask & (1 << i)) == 0)
 
928
                                        continue;
 
929
                                if (p->int_clocks > ((2000.0 - 0.5) * rmeas[i]))
 
930
                                        ns = 2000.0;                    /* Maximum edge count */
 
931
                                else {
 
932
                                        ns = floor(p->inttime * edgec[i] * p->clk_freq/rmeas[i] + 0.5);
 
933
                                        if (ns < ME)                    /* Minimum edge count */
 
934
                                                ns = ME;
 
935
                                }
 
936
                                edgec[i] = (int)ns;
 
937
                        }
 
938
                }
 
939
 
 
940
                /* Use frequency computed edge count if available */
 
941
                for (i = 0; i < 3; i++) {
 
942
                        if ((mask & (1 << i)) == 0)
 
943
                                continue;
 
944
                        if (cdgec[i] != ME)
 
945
                                edgec[i] = cdgec[i];
 
946
                }
 
947
        
 
948
                /* If we compute a different edge count, read again */
 
949
                if (edgec[0] > ME || edgec[1] > ME || edgec[2] > ME) {
 
950
                        double rmeas2[3];               /* 2nd RGB Readings */
 
951
        
 
952
                        DBG((dbgo,"Doing period re-measurement mask 0x%x, edgec %d %d %d\n",
 
953
                        mask, edgec[0], edgec[1], edgec[2]))
 
954
 
 
955
                        if ((ev = i1d2_period_measure(p, edgec, rmeas2)) != inst_ok)
 
956
                                return ev;
 
957
        
 
958
                        DBG((dbgo,"Got %f %f %f raw %f %f %f Hz\n",
 
959
                        rmeas[0], rmeas[1], rmeas[2],
 
960
                        (p->rgbadj[0] * 0.5 * (double)edgec[0] * p->clk_freq)/rmeas2[0],
 
961
                        (p->rgbadj[1] * 0.5 * (double)edgec[1] * p->clk_freq)/rmeas2[1],
 
962
                        (p->rgbadj[2] * 0.5 * (double)edgec[2] * p->clk_freq)/rmeas2[2]))
 
963
 
 
964
                        DBG((dbgo,"Int period %f %f %f secs\n",
 
965
                        rmeas2[0]/p->clk_freq, rmeas2[1]/p->clk_freq, rmeas2[2]/p->clk_freq))
 
966
 
 
967
                        /* Average readings if we repeated a measurement with the same count */
 
968
                        /* (Minor advantage, but may as well use it) */
 
969
                        for (i = 0; i < 3; i++) {
 
970
                                if (edgec[i] == ME)
 
971
                                        rmeas[i] = 0.5 * (rmeas[i] + rmeas2[i]);
 
972
                                else
 
973
                                        rmeas[i] = rmeas2[i];
 
974
                        }
 
975
                }
 
976
 
 
977
                /* Compute adjusted readings, ovewritting initial cooked values */
 
978
                for (i = 0; i < 3; i++) {
 
979
                        if ((mask & (1 << i)) == 0)
 
980
                                continue;
 
981
                        rgb[i] = (p->rgbadj[i] * 0.5 * (double)edgec[i] * p->clk_freq)/rmeas[i];
 
982
                        DBG((dbgo,"%d after scale = %f\n",i,rgb[i]))
 
983
        
 
984
                        rgb[i] -= p->reg103_F[i];               /* Subtract black level */
 
985
                        DBG((dbgo,"%d after sub black = %f\n",i,rgb[i]))
 
986
        
 
987
                        if (rgb[i] < 0.0001)
 
988
                                rgb[i] = 0.0001;
 
989
                        DBG((dbgo,"%d after limit min = %f\n",i,rgb[i]))
 
990
                }
 
991
        }
 
992
 
 
993
        DBG((dbgo,"Cooked RGB Hz = %f %f %f\n",rgb[0],rgb[1],rgb[2]))
 
994
        
 
995
        return inst_ok;
 
996
}
 
997
 
 
998
#else
 
999
/* Less precise (worse quatization errors), but more robust */
 
1000
/* against excessive delays if the light level drops during measurement. */
 
1001
/* Limits period measurement to an edge count < 35, but that can */
 
1002
/* still take a long time in the dark. */
 
1003
 
 
1004
/* Take a cooked measurement from the device for the i1d2 */
 
1005
static inst_code
 
1006
i1d2_take_measurement(
 
1007
        i1disp *p,                              /* Object */
 
1008
        int crtm,                               /* Measure in crt mode flag */
 
1009
        double rgb[3]                   /* Return the rgb values */
 
1010
) {
 
1011
        int i;
 
1012
        double rmeas[3];                        /* Raw measurement */
 
1013
        int edgec[3] = {ME,ME,ME};      /* Measurement edge count for each channel */
 
1014
        int cdgec[3] = {ME,ME,ME};      /* CRT computed edge count for re-measure */
 
1015
        int fmask = 0x0;             /* Freq re-measure mask */
 
1016
        int mask = 0x0;                         /* Period measure mask */
 
1017
        inst_code ev;
 
1018
 
 
1019
        if (p->inited == 0)
 
1020
                return i1disp_interp_code((inst *)p, I1DISP_NOT_INITED);
 
1021
 
 
1022
        if (p->dtype == 0)
 
1023
                return i1disp_interp_code((inst *)p, I1DISP_WRONG_DEVICE);
 
1024
 
 
1025
        DBG((dbgo, "i1d2_take_measurement called with crtm = %d\n",crtm));
 
1026
 
 
1027
        /* Do refresh period measurement */
 
1028
        if (crtm && p->rrset == 0) {
 
1029
                if ((ev = i1disp_do_fcal_setit(p)) != inst_ok)
 
1030
                        return ev;
 
1031
                p->rrset = 1;
 
1032
 
 
1033
                /* Quantize the sample time */
 
1034
                if (p->refperiod > 0.0) {
 
1035
                        int n;
 
1036
                        n = (int)ceil(p->dinttime/p->refperiod);
 
1037
                        p->inttime = n * p->refperiod;
 
1038
                        if (p->debug) fprintf(stderr,"i1disp: integration time quantize to %f secs\n",p->inttime);
 
1039
                } else {
 
1040
                        p->inttime = p->dinttime;       
 
1041
                        if (p->debug) fprintf(stderr,"i1disp: integration time set to %f secs\n",p->inttime);
 
1042
                }
 
1043
        }
 
1044
 
 
1045
        /* Do an initial fixed integration time frequency measurement. */
 
1046
        DBG((dbgo,"Doing fixed period frequency measurement over %f secs\n",p->inttime))
 
1047
 
 
1048
        if ((ev = i1d2_freq_measure(p, &p->inttime, rmeas)) != inst_ok)
 
1049
                return ev;
 
1050
 
 
1051
        for (i = 0; i < 3; i++)
 
1052
                rgb[i] = p->rgbadj[i] * 0.5 * rmeas[i]/p->inttime;
 
1053
 
 
1054
        DBG((dbgo,"Got %f %f %f raw, %f %f %f Hz\n",
 
1055
        rmeas[0], rmeas[1], rmeas[2], rgb[0], rgb[1], rgb[2]))
 
1056
 
 
1057
        /* Decide whether any channels need re-measuring. */
 
1058
        /* Threshold is a count of 75, and switch to period */
 
1059
        /* measurement mode on count less than 37. */
 
1060
        fmask = 0x0;
 
1061
        for (i = 0; i < 3; i++) {
 
1062
 
 
1063
                if (rmeas[i] <= 75.0) {
 
1064
                        fmask |= (1 << i);              /* Yes, do another freq re-measure */
 
1065
 
 
1066
                        if (rmeas[i] <= 37.5) { 
 
1067
                                mask |= (1 << i);               /* Do a period re-measure */
 
1068
                                fmask = 0;                              /* Don't bother with freq re-measure */  
 
1069
                        }
 
1070
                        if (rmeas[i] >= 10.0) { /* Compute target edges */
 
1071
                                cdgec[i] = (int)(2.0 * rgb[i] * p->inttime + 0.5); 
 
1072
                                if (cdgec[i] > 2000)
 
1073
                                        cdgec[i] = 2000;
 
1074
                                else if (cdgec[i] < ME)
 
1075
                                        cdgec[i] = ME;
 
1076
                        }
 
1077
                }
 
1078
        }
 
1079
        DBG((dbgo,"Freq mask = 0x%x, Period mask 0x%x\n",fmask, mask))
 
1080
        DBG((dbgo,"cdgec = %d %d %d\n",cdgec[0],cdgec[1],cdgec[2]))
 
1081
 
 
1082
        /* If there is a frequency re-measure */
 
1083
        /* ** This doesn't actually work. The quantization error */
 
1084
        /* for each read is 0.5, but averaging 2 reads it drops */
 
1085
        /* to 0.354, not the desired 0.25 that would have been */
 
1086
        /* acheived with double the integration time. ** */ 
 
1087
        if (fmask != 0) {
 
1088
                DBG((dbgo,"Doing frequency re-measurement over %f secs\n",p->inttime))
 
1089
                if ((ev = i1d2_freq_measure(p, &p->inttime, rmeas)) != inst_ok)
 
1090
                        return ev;
 
1091
 
 
1092
                for (i = 0; i < 3; i++) {
 
1093
                        rgb[i] += p->rgbadj[i] * 0.5 * rmeas[i]/p->inttime;
 
1094
                        rgb[i] /= 2.0;
 
1095
                }
 
1096
 
 
1097
                DBG((dbgo,"Got %f %f %f raw, %f %f %f Avg. Hz\n",
 
1098
                rmeas[0], rmeas[1], rmeas[2], rgb[0], rgb[1], rgb[2]))
 
1099
 
 
1100
        /* If there is a period re-measure */
 
1101
        } else if (mask != 0) {
 
1102
 
 
1103
                /* See if we need to compute a target edge count */
 
1104
                for (i = 0; i < 3; i++) {
 
1105
                        if ((mask & (1 << i)) && cdgec[i] == ME)
 
1106
                                break;
 
1107
                }
 
1108
 
 
1109
                /* Yes we do */
 
1110
                if (i < 3) {
 
1111
 
 
1112
                        DBG((dbgo,"Doing 1st period pre-measurement mask 0x%x, edgec %d %d %d\n",
 
1113
                        mask, edgec[0], edgec[1], edgec[2]))
 
1114
 
 
1115
                        /* Do an initial measurement of 1 edge to estimate the */
 
1116
                        /* number of edges needed for the whole integration time. */
 
1117
                        if ((ev = i1d2_period_measure(p, edgec, rmeas)) != inst_ok)
 
1118
                                return ev;
 
1119
 
 
1120
                        DBG((dbgo,"Got %f %f %f raw %f %f %f Hz\n",
 
1121
                        rmeas[0], rmeas[1], rmeas[2],
 
1122
                        (p->rgbadj[0] * 0.5 * (double)edgec[0] * p->clk_freq)/rmeas[0],
 
1123
                        (p->rgbadj[1] * 0.5 * (double)edgec[1] * p->clk_freq)/rmeas[1],
 
1124
                        (p->rgbadj[2] * 0.5 * (double)edgec[2] * p->clk_freq)/rmeas[2]))
 
1125
 
 
1126
                        /* Compute adjusted edge count for channels we're remeasuring, */
 
1127
                        /* aiming for a values of int_clocks. */
 
1128
                        for (i = 0; i < 3; i++) {
 
1129
                                double ns;
 
1130
                                if ((mask & (1 << i)) == 0)
 
1131
                                        continue;
 
1132
                                if (p->int_clocks > ((2000.0 - 0.5) * rmeas[i]))
 
1133
                                        ns = 2000.0;                    /* Maximum edge count */
 
1134
                                else {
 
1135
                                        ns = floor(p->inttime * edgec[i] * p->clk_freq/rmeas[i] + 0.5);
 
1136
                                        if (ns < ME)                    /* Minimum edge count */
 
1137
                                                ns = ME;
 
1138
                                }
 
1139
                                edgec[i] = (int)ns;
 
1140
 
 
1141
                                /* Sanity check cdgec value, in case light level has changed */
 
1142
                                if ((edgec[i] * 3) < (cdgec[i] * 2)) {
 
1143
                                        cdgec[i] = edgec[i];
 
1144
                                }
 
1145
                        }
 
1146
                }
 
1147
 
 
1148
                /* Use frequency computed edge count if available */
 
1149
                for (i = 0; i < 3; i++) {
 
1150
                        if ((mask & (1 << i)) == 0)
 
1151
                                continue;
 
1152
                        if (cdgec[i] != ME)
 
1153
                                edgec[i] = cdgec[i];
 
1154
                }
 
1155
        
 
1156
                /* If we compute a different edge count, read again */
 
1157
                if (edgec[0] > ME || edgec[1] > ME || edgec[2] > ME) {
 
1158
                        double rmeas2[3];               /* 2nd RGB Readings */
 
1159
        
 
1160
                        DBG((dbgo,"Doing period re-measurement mask 0x%x, edgec %d %d %d\n",
 
1161
                        mask, edgec[0], edgec[1], edgec[2]))
 
1162
 
 
1163
                        if ((ev = i1d2_period_measure(p, edgec, rmeas2)) != inst_ok)
 
1164
                                return ev;
 
1165
        
 
1166
                        DBG((dbgo,"Got %f %f %f raw %f %f %f Hz\n",
 
1167
                        rmeas[0], rmeas[1], rmeas[2],
 
1168
                        (p->rgbadj[0] * 0.5 * (double)edgec[0] * p->clk_freq)/rmeas2[0],
 
1169
                        (p->rgbadj[1] * 0.5 * (double)edgec[1] * p->clk_freq)/rmeas2[1],
 
1170
                        (p->rgbadj[2] * 0.5 * (double)edgec[2] * p->clk_freq)/rmeas2[2]))
 
1171
 
 
1172
                        DBG((dbgo,"Int period %f %f %f secs\n",
 
1173
                        rmeas2[0]/p->clk_freq, rmeas2[1]/p->clk_freq, rmeas2[2]/p->clk_freq))
 
1174
 
 
1175
                        /* Average readings if we repeated a measurement with the same count */
 
1176
                        /* (Minor advantage, but may as well use it) */
 
1177
                        for (i = 0; i < 3; i++) {
 
1178
                                if (edgec[i] == ME)
 
1179
                                        rmeas[i] = 0.5 * (rmeas[i] + rmeas2[i]);
 
1180
                                else
 
1181
                                        rmeas[i] = rmeas2[i];
 
1182
                        }
 
1183
                }
 
1184
 
 
1185
                /* Compute adjusted readings, ovewritting initial cooked values */
 
1186
                for (i = 0; i < 3; i++) {
 
1187
                        if ((mask & (1 << i)) == 0)
 
1188
                                continue;
 
1189
                        rgb[i] = (p->rgbadj[i] * 0.5 * (double)edgec[i] * p->clk_freq)/rmeas[i];
 
1190
                        DBG((dbgo,"%d after scale = %f\n",i,rgb[i]))
 
1191
        
 
1192
                        rgb[i] -= p->reg103_F[i];               /* Subtract black level */
 
1193
                        DBG((dbgo,"%d after sub black = %f\n",i,rgb[i]))
 
1194
        
 
1195
                        if (rgb[i] < 0.0001)
 
1196
                                rgb[i] = 0.0001;
 
1197
                        DBG((dbgo,"%d after limit min = %f\n",i,rgb[i]))
 
1198
                }
 
1199
        }
 
1200
 
 
1201
        DBG((dbgo,"Cooked RGB Hz = %f %f %f\n",rgb[0],rgb[1],rgb[2]))
 
1202
        
 
1203
        return inst_ok;
 
1204
}
 
1205
#endif
898
1206
#undef ME
899
1207
 
900
1208
/* . . . . . . . . . . . . . . . . . . . . . . . . */
911
1219
        double *mat;            /* Pointer to matrix */
912
1220
 
913
1221
        if (p->dtype == 0) {            /* i1 disp 1 */
914
 
                if ((ev = i1disp_take_measurement_1(p, 0, rgb)) != inst_ok)
 
1222
                if ((ev = i1d1_take_measurement(p, 0, rgb)) != inst_ok)
915
1223
                        return ev;
916
1224
        } else {                                /* i1 disp 2 */
917
1225
                int crtm = 0;           /* Assume LCD or ambient */
920
1228
                        crtm = 1; 
921
1229
                }
922
1230
 
923
 
                if ((ev = i1disp_take_measurement_2(p, crtm, rgb)) != inst_ok)
 
1231
                if ((ev = i1d2_take_measurement(p, crtm, rgb)) != inst_ok)
924
1232
                        return ev;
925
1233
        }
926
1234
 
945
1253
                        XYZ[i] *= 4.0/3.0;                      /* (Not sure about this factor!) */
946
1254
#endif
947
1255
        }
 
1256
 
 
1257
        if ((p->mode & inst_mode_measurement_mask) != inst_mode_emis_ambient) {
 
1258
 
 
1259
                /* Apply the colorimeter correction matrix */
 
1260
                icmMulBy3x3(XYZ, p->ccmat, XYZ);
 
1261
        }
 
1262
 
948
1263
        DBG((dbgo,"returning XYZ = %f %f %f\n",XYZ[0],XYZ[1],XYZ[2]))
949
1264
        return inst_ok;
950
1265
}
954
1269
i1disp_do_black_cal(
955
1270
        i1disp *p                               /* Object */
956
1271
) {
957
 
        int i, j;
 
1272
        int i;
958
1273
        double rgb1[3], rgb2[3];        /* RGB Readings */
959
1274
        inst_code ev;
960
1275
 
962
1277
                return i1disp_interp_code((inst *)p, I1DISP_CANT_BLACK_CALIB);
963
1278
 
964
1279
        /* Do a couple of readings without subtracting the black */
965
 
        if ((ev = i1disp_take_measurement_1(p, 1, rgb1)) != inst_ok)
 
1280
        if ((ev = i1d1_take_measurement(p, 1, rgb1)) != inst_ok)
966
1281
                return ev;
967
 
        if ((ev = i1disp_take_measurement_1(p, 1, rgb2)) != inst_ok)
 
1282
        if ((ev = i1d1_take_measurement(p, 1, rgb2)) != inst_ok)
968
1283
                return ev;
969
1284
 
970
1285
        /* Average the results */
987
1302
        return inst_ok;
988
1303
}
989
1304
 
990
 
/* Do a measurement period cailbration if CRT and set integration time */
 
1305
/* Do a refersh period cailbration */
991
1306
static inst_code
992
1307
i1disp_do_fcal_setit(
993
1308
        i1disp *p                               /* Object */
1003
1318
 
1004
1319
        if (p->crt && (p->mode & inst_mode_measurement_mask) != inst_mode_emis_ambient) {
1005
1320
 
1006
 
                /* Average a few measurement period readings */
 
1321
                /* Average a few refresh period readings */
1007
1322
                for (i = 0; i < p->nmeasprds; i++) {
1008
1323
                        int mp;
1009
1324
        
1010
 
                        if ((ev = i1disp_rd_meas_period(p, &mp)) != inst_ok)
 
1325
                        /* Measures period in clocks */
 
1326
                        if ((ev = i1disp_rd_meas_ref_period(p, &mp)) != inst_ok)
1011
1327
                                return ev;
1012
1328
                        if (mp == 0)
1013
1329
                                break;                  /* Too dark to measure */
1016
1332
 
1017
1333
                /* Compute the measurement frequency */
1018
1334
                if (measp != 0.0) {
1019
 
                        measp /= (double)p->nmeasprds;
1020
 
                        measp *= p->clk_prd;            /* Multiply by master clock period to get seconds */
1021
 
                        p->sampfreq = 1.0/measp;        /* Measurement sample frequency */
1022
 
                        DBG((dbgo,"Sample frequency measured = %f\n",p->sampfreq))
 
1335
                        p->refperiod = measp/(p->clk_freq * (double)p->nmeasprds);      
 
1336
                        DBG((dbgo,"Sample frequency measured = %f\n",1.0/p->refperiod))
1023
1337
                } else {
1024
 
                        p->sampfreq = 60.0;
 
1338
                        DBG((dbgo,"No discernable refresh frequency measured\n"))
1025
1339
                }
1026
 
        } else {
1027
 
                p->sampfreq = 100.0;    /* Make integration clocks = 1e6, same as default */
1028
1340
        }
1029
 
 
1030
 
        /* Compute actual sampling time */
1031
 
        p->samptime = p->sampno / p->sampfreq;
1032
 
        DBG((dbgo,"Computed sample time = %f seconds\n",p->samptime))
1033
 
 
1034
 
        /* Compute the integration period in clocks rounded to sample frequency */
1035
 
        p->int_clocks = (int)floor((double)p->sampno/((double)p->reg40_S * 1e-9 * p->sampfreq) + 0.5);
1036
 
 
1037
 
        DBG((dbgo,"Setting integration time to = %d clocks\n",p->int_clocks))
1038
 
        if ((ev = i1disp_wr_int_time(p, p->int_clocks)) != inst_ok)
1039
 
                return ev;
1040
 
 
1041
 
        /* Read the integration time (could it be limited by instrument?) */
1042
 
        if ((ev = i1disp_rd_int_time(p, &p->int_clocks) ) != inst_ok)
1043
 
                return ev;
1044
 
        DBG((dbgo,"Actual integration time = %d clocks\n",p->int_clocks))
1045
 
 
1046
 
        p->itset = 1;
1047
1341
        return inst_ok;
1048
1342
}
1049
1343
 
1065
1359
                unsigned char code[4];
1066
1360
                int *flag;
1067
1361
        } codes[] = {
1068
 
                { { 'G','r','M','b' }, NULL },                  /* i1 Display */
1069
 
                { { 'L','i','t','e' }, &p->lite },              /* i1 Display LT */
1070
 
                { { 'M','u','n','k' }, &p->munki },             /* ColorMunki Create */
1071
 
                { { 'O','b','i','W' }, &p->hpdream },   /* HP DreamColor */
1072
 
                { { 'O','b','i','w' }, &p->hpdream },   /* HP DreamColor */
1073
 
                { { 'C','M','X','2' }, &p->calmanx2 },  /* Calman X2 */
 
1362
                { { 'G','r','M','b' }, NULL },                  /* "GrMb" i1 Display */
 
1363
                { { 'L','i','t','e' }, &p->lite },              /* "Lite" i1 Display LT */
 
1364
                { { 'M','u','n','k' }, &p->munki },             /* "Munk" ColorMunki Create */
 
1365
                { { 'O','b','i','W' }, &p->hpdream },   /* "ObiW" HP DreamColor */
 
1366
                { { 'O','b','i','w' }, &p->hpdream },   /* "Obiw" HP DreamColor */
 
1367
                { { 'C','M','X','2' }, &p->calmanx2 },  /* "CMX2" Calman X2 */
1074
1368
                { { 'R','G','B','c' }, NULL },                  /* */
1075
1369
                { { 'C','E','C','5' }, NULL },                  /* */
1076
1370
                { { 'C','M','C','5' }, NULL },                  /* */
1078
1372
                { { 0x00,0x00,0x01,0x00 }, NULL },              /* */
1079
1373
                { { 0x09,0x0b,0x0c,0x0d }, NULL },              /* */
1080
1374
                { { 0x0e,0x0e,0x0e,0x0e }, NULL },              /* */
 
1375
                { { 0x11,0x02,0xde,0xf0 }, NULL },              /* Barco Chroma 5 ? */
1081
1376
                { { ' ',' ',' ',' ' }, (int *)-1 }
1082
1377
        }; 
1083
1378
 
1141
1436
 
1142
1437
        DBG((dbgo,"Version character = 0x%02x = '%c'\n",vv,vv))
1143
1438
 
1144
 
        if (ver >= 4.0 && ver < 5.1 && vv == 0xff) {
 
1439
        /* Sequel Chroma 4 with vv == 0xff ? */
 
1440
        /* Barco Chroma 5 with ver = 5.01 and vv = '5' */
 
1441
        if (ver >= 4.0 && ver < 5.1
 
1442
         && (vv == 0xff || vv == 0x35)) {
1145
1443
                p->dtype = 0;                   /* Sequel Chroma 4 ?? */
1146
1444
                p->chroma4 = 1;                 /* Treat like an Eye-One Display 1 */
1147
1445
                                                                /* !!! Not fully tested !!! */
1188
1486
        /* LCD/user calibration time */
1189
1487
        if ((ev = i1disp_rdreg_word(p, &p->reg50_W, 50) ) != inst_ok)
1190
1488
                return ev;
1191
 
        DBG((dbgo,"LCD/user calibration time = 0x%x = %s\n",p->reg50_W, ctime((time_t *)&p->reg50_W)))
 
1489
        DBG((dbgo,"LCD/user calibration time = 0x%x = %s\n",p->reg50_W, ctime_32(&p->reg50_W)))
1192
1490
 
1193
1491
        /* LCD/user calibration flag */
1194
1492
        if ((ev = i1disp_rdreg_short(p, &p->reg126_S, 126) ) != inst_ok)
1205
1503
        /* CRT/factory calibration flag */
1206
1504
        if ((ev = i1disp_rdreg_word(p, &p->reg90_W, 90) ) != inst_ok)
1207
1505
                return ev;
1208
 
        DBG((dbgo,"CRT/factory flag = 0x%x = %s\n",p->reg90_W, ctime((time_t *)&p->reg90_W)))
1209
 
 
1210
 
 
1211
 
        /* Calibration factor */
 
1506
        DBG((dbgo,"CRT/factory flag = 0x%x = %s\n",p->reg90_W, ctime_32(&p->reg90_W)))
 
1507
 
 
1508
 
 
1509
        /* Integration clock period in nsec */
1212
1510
        if ((ev = i1disp_rdreg_short(p, &p->reg40_S, 40) ) != inst_ok)
1213
1511
                return ev;
1214
1512
        DBG((dbgo,"Reg40 = %d\n",p->reg40_S))
1225
1523
                DBG((dbgo,"reg44[%d] = %d\n",i,p->reg44_S[i]))
1226
1524
        }
1227
1525
 
1228
 
 
1229
 
        /* Overall reading scale value ?? */
 
1526
        /* Measurement/master clock period */
1230
1527
        if ((ev = i1disp_rdreg_float(p, &p->clk_prd, 94) ) != inst_ok)
1231
1528
                return ev;
1232
 
        DBG((dbgo,"Clock Period = %e\n",p->clk_prd))
 
1529
        DBG((dbgo,"Master clock Frequency = %e\n",1/p->clk_prd))
1233
1530
 
1234
1531
        /* unknown */
1235
1532
        if ((ev = i1disp_rdreg_word(p, &p->reg98_W, 98) ) != inst_ok)
1236
1533
                return ev;
1237
 
        DBG((dbgo,"reg98 = 0x%x = %s\n",p->reg98_W,ctime((time_t *)&p->reg98_W)))
 
1534
        DBG((dbgo,"reg98 = 0x%x = %s\n",p->reg98_W,ctime_32(&p->reg98_W)))
1238
1535
 
1239
1536
        /* unknown */
1240
1537
        if ((ev = i1disp_rdreg_byte(p, &p->reg102_B, 102) ) != inst_ok)
1314
1611
        if (p->reg0_W == 0xffffffff)
1315
1612
                return i1disp_interp_code((inst *)p, I1DISP_BAD_SERIAL_NUMBER);
1316
1613
 
 
1614
        /* LCD calibration date valid ? */
1317
1615
        if (p->reg50_W == 0xffffffff)
1318
1616
                return i1disp_interp_code((inst *)p, I1DISP_BAD_LCD_CALIBRATION);
1319
1617
 
1320
 
        /* The value stored in reg126_S seems hard to interpret. */
 
1618
        /* The value stored in reg126_S ("user cal flag") seems hard to interpret. */
1321
1619
        /* For the i1display 1&2, it has a value of 0xd. */
1322
1620
        /* Value 0x7 seems to be for a "user calibration" */
1323
1621
        /* Values 3 & 6 seem to always "errors" as does a value */
1324
1622
        /* < 7 in most circumstances. But the Heidelberg Viewmaker */
1325
1623
        /* (from Sequel Imaging) and Lacie Blue Eye colorimeter seems to have a value of 2. */
 
1624
        /* The Barco sensor seems to have a value of 0x20 */
1326
1625
        if (p->reg126_S == 0xffffffff || (p->reg126_S < 7 && p->reg126_S != 2))
1327
1626
                return i1disp_interp_code((inst *)p, I1DISP_BAD_LCD_CALIBRATION);
1328
1627
 
1329
 
        if (p->reg90_W == 0xffffffff)
1330
 
                return i1disp_interp_code((inst *)p, I1DISP_BAD_CRT_CALIBRATION);
1331
 
 
1332
1628
        /* Not quite sure about this, but we're assuming this */
1333
1629
        /* is set to 2 or 0xd if reg4-36 hold the LCD calibration, */
1334
1630
        /* and some other number if they are not set, or set */
1335
1631
        /* to a custom user calibration. */
1336
 
        if (p->reg126_S != 0xd && p->reg126_S != 2)
 
1632
        if (p->reg126_S != 0xd && p->reg126_S != 2 && p->reg126_S != 0x20)
1337
1633
                return i1disp_interp_code((inst *)p, I1DISP_BAD_LCD_CALIBRATION);
1338
1634
                
 
1635
        if (p->reg90_W == 0xffffffff)
 
1636
                return i1disp_interp_code((inst *)p, I1DISP_BAD_CRT_CALIBRATION);
 
1637
 
1339
1638
        /* Compute ambient matrix */
1340
1639
        for (i = 0; i < 9; i++)
1341
1640
                p->amb[i] = p->reg144_F[i % 3] * 0.5 * (p->reg4_F[i] + p->reg54_F[i]);
1342
1641
 
1343
 
        /* clk_prd inversion */
 
1642
        /* Integration clock frequency */
 
1643
        p->iclk_freq = 1.0/(p->reg40_S * 1e-9);
 
1644
 
 
1645
        /* Master/Measurement clock frequency */
1344
1646
        p->clk_freq = 1.0/p->clk_prd;
1345
 
        DBG((dbgo,"clk_freq = %f\n",p->clk_freq))
1346
 
        
1347
 
        /* RGB channel scale factors */
 
1647
 
 
1648
        /* RGB channel calibration factors */
1348
1649
        for (i = 0; i < 3; i++) {
1349
 
                double tt;
1350
 
                tt = (double)p->reg44_S[i] * 1e11/((double)p->reg40_S * (double)p->reg42_S);
1351
 
                p->rgbadj1[i] = floor(tt + 0.5);
1352
 
                DBG((dbgo,"reg44+%dcalc = %f\n",i,p->rgbadj1[i]))
1353
 
                p->rgbadj2[i] = tt * 1e-9 * (double)p->reg40_S;
1354
 
                DBG((dbgo,"reg44+%dcalc2 = %f\n",i,p->rgbadj2[i]))
 
1650
 
 
1651
                /* Individual channel calibration factors, typically 1.0 */
 
1652
                p->rgbadj[i] = (double)p->reg44_S[i] * 100.0/(double)p->reg42_S;
 
1653
                DBG((dbgo,"reg44+%dcalc2 = %f\n",i,p->rgbadj[i]))
1355
1654
        }
1356
1655
 
1357
1656
        /* Set some defaults */
1358
 
        p->sampfreq = 60.0;             /* Display refresh rate/sample frequency */
1359
 
        p->sampno = 100;                /* Minimum sampling count. Set target integration time. */
1360
1657
        p->nmeasprds = 5;               /* Number of disp refresh period measurments to average */ 
1361
1658
                                                        /* in doing frequency calibration */
 
1659
        p->dinttime = 1.0;              /* 1.0 second integration time default */
 
1660
        p->inttime = p->dinttime;       /* Current integration time */
1362
1661
 
1363
1662
        return inst_ok;
1364
1663
}
1373
1672
        i1disp *p = (i1disp *) pp;
1374
1673
        unsigned char buf[16];
1375
1674
        int rsize;
1376
 
        long etime;
1377
 
        int bi, i, rv;
1378
1675
        inst_code ev = inst_ok;
1379
1676
 
1380
1677
        if (p->debug) {
1436
1733
                if (p->debug) fprintf(dbgo,"i1disp: instrument inited OK\n");
1437
1734
        }
1438
1735
 
1439
 
        p->itype = instI1Display;
1440
 
 
1441
1736
        return ev;
1442
1737
}
1443
1738
 
1452
1747
        int user_trig = 0;
1453
1748
        int rv = inst_protocol_error;
1454
1749
 
 
1750
        if (!p->gotcoms)
 
1751
                return inst_no_coms;
 
1752
        if (!p->inited)
 
1753
                return inst_no_init;
 
1754
 
1455
1755
        if (p->trig == inst_opt_trig_keyb) {
1456
1756
                int se;
1457
1757
                if ((se = icoms_poll_user(p->icom, 1)) != ICOM_TRIG) {
1467
1767
        if ((rv = i1disp_take_XYZ_measurement(p, val->aXYZ)) != inst_ok)
1468
1768
                return rv;
1469
1769
 
1470
 
        /* Apply the colorimeter correction matrix */
1471
 
        icmMulBy3x3(val->aXYZ, p->ccmat, val->aXYZ);
1472
 
 
1473
1770
        val->XYZ_v = 0;
1474
1771
        val->aXYZ_v = 1;                /* These are absolute XYZ readings ? */
1475
1772
        val->Lab_v = 0;
1490
1787
) {
1491
1788
        i1disp *p = (i1disp *)pp;
1492
1789
 
 
1790
        if (!p->gotcoms)
 
1791
                return inst_no_coms;
 
1792
        if (!p->inited)
 
1793
                return inst_no_init;
 
1794
 
1493
1795
        if (mtx == NULL)
1494
1796
                icmSetUnity3x3(p->ccmat);
1495
1797
        else
1505
1807
inst_cal_type i1disp_needs_calibration(inst *pp) {
1506
1808
        i1disp *p = (i1disp *)pp;
1507
1809
 
1508
 
        if (p->dtype == 1 && p->crt != 0 && p->itset == 0)
 
1810
        if (!p->gotcoms)
 
1811
                return inst_no_coms;
 
1812
        if (!p->inited)
 
1813
                return inst_no_init;
 
1814
 
 
1815
        if (p->dtype == 1 && p->crt != 0 && p->rrset == 0)
1509
1816
                return inst_calt_crt_freq;
1510
1817
        return inst_ok;
1511
1818
}
1526
1833
        i1disp *p = (i1disp *)pp;
1527
1834
        int rv = 0;
1528
1835
 
 
1836
        if (!p->gotcoms)
 
1837
                return inst_no_coms;
 
1838
        if (!p->inited)
 
1839
                return inst_no_init;
 
1840
 
1529
1841
        id[0] = '\000';
1530
1842
 
1531
1843
        /* Translate default into what's needed or expected default */
1562
1874
                        /* Do CRT frequency calibration and set integration time */
1563
1875
                        if ((rv = i1disp_do_fcal_setit(p)) != inst_ok)
1564
1876
                                return rv;
 
1877
                        p->rrset = 1;
 
1878
 
 
1879
                        /* Quantize the sample time */
 
1880
                        if (p->refperiod > 0.0) {
 
1881
                                int n;
 
1882
                                n = (int)ceil(p->dinttime/p->refperiod);
 
1883
                                p->inttime = n * p->refperiod;
 
1884
                                if (p->debug) fprintf(stderr,"i1disp: integration time quantize to %f secs\n",p->inttime);
 
1885
                        } else {
 
1886
                                p->inttime = p->dinttime;       
 
1887
                                if (p->debug) fprintf(stderr,"i1disp: integration time set to %f secs\n",p->inttime);
 
1888
                        }
1565
1889
 
1566
1890
                        return inst_ok;
1567
1891
                }
1715
2039
 
1716
2040
        rv = inst_emis_spot
1717
2041
           | inst_emis_disp
1718
 
           | inst_emis_disp_crt
1719
 
           | inst_emis_disp_lcd
 
2042
           | inst_emis_disptype
 
2043
           | inst_emis_disptypem
1720
2044
           | inst_colorimeter
1721
2045
           | inst_ccmx
1722
2046
             ;
1723
2047
 
1724
 
        if (p->dtype == 1) {    /* Eye-One Display 2 */
 
2048
        /* Eye-One Display 2 has ambient capability */
 
2049
        if (p->dtype == 1)
1725
2050
           rv |= inst_emis_ambient;
1726
 
        }
1727
2051
 
1728
2052
        return rv;
1729
2053
}
1744
2068
        return rv;
1745
2069
}
1746
2070
 
 
2071
inst_disptypesel i1disp_disptypesel[3] = {
 
2072
        {
 
2073
                1,
 
2074
                "c",
 
2075
                "i1Disp: CRT display",
 
2076
                1
 
2077
        },
 
2078
        {
 
2079
                2,
 
2080
                "l",
 
2081
                "i1Disp: LCD display",
 
2082
                0
 
2083
        },
 
2084
        {
 
2085
                0,
 
2086
                "",
 
2087
                "",
 
2088
                -1
 
2089
        }
 
2090
};
 
2091
 
 
2092
/* Get mode and option details */
 
2093
static inst_code i1disp_get_opt_details(
 
2094
inst *pp,
 
2095
inst_optdet_type m,     /* Requested option detail type */
 
2096
...) {                          /* Status parameters */                             
 
2097
 
 
2098
        if (m == inst_optdet_disptypesel) {
 
2099
                va_list args;
 
2100
                int *pnsels;
 
2101
                inst_disptypesel **psels;
 
2102
 
 
2103
                va_start(args, m);
 
2104
                pnsels = va_arg(args, int *);
 
2105
                psels = va_arg(args, inst_disptypesel **);
 
2106
                va_end(args);
 
2107
 
 
2108
                *pnsels = 2;
 
2109
                *psels = i1disp_disptypesel;
 
2110
                
 
2111
                return inst_ok;
 
2112
        }
 
2113
 
 
2114
        return inst_unsupported;
 
2115
}
 
2116
 
1747
2117
/* Set device measurement mode */
1748
2118
inst_code i1disp_set_mode(inst *pp, inst_mode m)
1749
2119
{
1750
2120
        i1disp *p = (i1disp *)pp;
1751
2121
        inst_mode mm;           /* Measurement mode */
1752
2122
 
 
2123
        if (!p->gotcoms)
 
2124
                return inst_no_coms;
 
2125
        if (!p->inited)
 
2126
                return inst_no_init;
 
2127
 
1753
2128
        /* The measurement mode portion of the mode */
1754
2129
        mm = m & inst_mode_measurement_mask;
1755
2130
 
1776
2151
i1disp_set_opt_mode(inst *pp, inst_opt_mode m, ...)
1777
2152
{
1778
2153
        i1disp *p = (i1disp *)pp;
1779
 
        inst_code ev = inst_ok;
1780
 
 
1781
 
        if (m == inst_opt_disp_crt) {
1782
 
                if (p->crt == 0)
1783
 
                        p->itset = 0;           /* This is a hint we may have swapped displays */
1784
 
                p->crt = 1;
1785
 
                return inst_ok;
1786
 
        } else if (m == inst_opt_disp_lcd) {
1787
 
                if (p->crt != 0)
1788
 
                        p->itset = 0;           /* This is a hint we may have swapped displays */
1789
 
                p->crt = 0;
1790
 
                return inst_ok;
1791
 
 
 
2154
 
 
2155
        if (!p->gotcoms)
 
2156
                return inst_no_coms;
 
2157
        if (!p->inited)
 
2158
                return inst_no_init;
 
2159
 
 
2160
        /* Set the display type */
 
2161
        if (m == inst_opt_disp_type) {
 
2162
                va_list args;
 
2163
                int ix;
 
2164
 
 
2165
                va_start(args, m);
 
2166
                ix = va_arg(args, int);
 
2167
                va_end(args);
 
2168
 
 
2169
                if (ix == 1) {
 
2170
                        if (p->crt == 0)
 
2171
                                p->rrset = 0;           /* This is a hint we may have swapped displays */
 
2172
                        p->crt = 1;
 
2173
                        return inst_ok;
 
2174
                } else if (ix == 2) {
 
2175
                        if (p->crt != 0)
 
2176
                                p->rrset = 0;           /* This is a hint we may have swapped displays */
 
2177
                        p->crt = 0;
 
2178
                        return inst_ok;
 
2179
                } else {
 
2180
                        return inst_unsupported;
 
2181
                }
1792
2182
        }
 
2183
 
1793
2184
        /* Record the trigger mode */
1794
2185
        if (m == inst_opt_trig_prog
1795
2186
         || m == inst_opt_trig_keyb) {
1808
2199
}
1809
2200
 
1810
2201
/* Constructor */
1811
 
extern i1disp *new_i1disp(icoms *icom, int debug, int verb)
 
2202
extern i1disp *new_i1disp(icoms *icom, instType itype, int debug, int verb)
1812
2203
{
1813
2204
        i1disp *p;
1814
2205
        if ((p = (i1disp *)calloc(sizeof(i1disp),1)) == NULL)
1828
2219
        p->init_inst         = i1disp_init_inst;
1829
2220
        p->capabilities      = i1disp_capabilities;
1830
2221
        p->capabilities2     = i1disp_capabilities2;
 
2222
        p->get_opt_details   = i1disp_get_opt_details;
1831
2223
        p->set_mode          = i1disp_set_mode;
1832
2224
        p->set_opt_mode      = i1disp_set_opt_mode;
1833
2225
        p->read_sample       = i1disp_read_sample;
1837
2229
        p->interp_error      = i1disp_interp_error;
1838
2230
        p->del               = i1disp_del;
1839
2231
 
1840
 
        p->itype = instUnknown;         /* Until initalisation */
 
2232
        p->itype = itype;
 
2233
 
 
2234
        if (p->itype == instI1Disp2)
 
2235
                p->dtype = 1;                   /* i1Display2 */
1841
2236
 
1842
2237
        return p;
1843
2238
}