add support for 67xx boards. Doesn't work yet, due to unknown reference
authorFrank Mori Hess <fmhess@speakeasy.net>
Sun, 15 Feb 2004 22:24:57 +0000 (22:24 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Sun, 15 Feb 2004 22:24:57 +0000 (22:24 +0000)
of internal calibration adc.  On my board, it's input seems to be about
2% off from +-10V.

comedi_calibrate/cal_common.c
comedi_calibrate/calib.h
comedi_calibrate/comedi_calibrate.c
comedi_calibrate/ni.c

index b57f11ac45990cc79bd96d85ec7e1d8b6f3d1f1c..7f99c7a448de92468e5cb7540e705a4c82905994 100644 (file)
@@ -101,8 +101,10 @@ void generic_prep_dac_caldacs( calibration_setup_t *setup,
        {
                reset_caldac( setup, layout->dac_offset( channel ) );
                reset_caldac( setup, layout->dac_gain( channel ) );
+               reset_caldac( setup, layout->dac_linearity( channel ) );
                reset_caldac( setup, layout->dac_offset_fine( channel ) );
                reset_caldac( setup, layout->dac_gain_fine( channel ) );
+               reset_caldac( setup, layout->dac_linearity_fine( channel ) );
        }else
        {
                retval = comedi_apply_parsed_calibration( setup->dev, setup->da_subdev,
@@ -112,8 +114,10 @@ void generic_prep_dac_caldacs( calibration_setup_t *setup,
                        DPRINT( 0, "Failed to apply existing calibration, reseting dac caldacs.\n" );
                        reset_caldac( setup, layout->dac_offset( channel ) );
                        reset_caldac( setup, layout->dac_gain( channel ) );
+                       reset_caldac( setup, layout->dac_linearity( channel ) );
                        reset_caldac( setup, layout->dac_offset_fine( channel ) );
                        reset_caldac( setup, layout->dac_gain_fine( channel ) );
+                       reset_caldac( setup, layout->dac_linearity_fine( channel ) );
                }
        }
 }
@@ -161,10 +165,19 @@ static void generic_do_dac_channel( calibration_setup_t *setup, const generic_la
 
        for( i = 0; i < max_iterations; i++ )
        {
+               generic_do_linearity(setup, current_cal, layout->dac_ground_observable( setup, channel, range ),
+                       layout->dac_mid_observable( setup, channel, range ),
+                       layout->dac_high_observable( setup, channel, range ),
+                       layout->dac_linearity(channel));
                generic_do_relative( setup, current_cal, layout->dac_high_observable( setup, channel, range ),
                        layout->dac_ground_observable( setup, channel, range ),layout->dac_gain( channel ) );
                generic_do_cal( setup, current_cal, layout->dac_ground_observable( setup, channel, range ),
                        layout->dac_offset( channel ) );
+
+               generic_do_linearity(setup, current_cal, layout->dac_ground_observable( setup, channel, range ),
+                       layout->dac_mid_observable( setup, channel, range ),
+                       layout->dac_high_observable( setup, channel, range ),
+                       layout->dac_linearity_fine(channel));
                generic_do_relative( setup, current_cal, layout->dac_high_observable( setup, channel, range ),
                        layout->dac_ground_observable( setup, channel, range ), layout->dac_gain_fine( channel ) );
                generic_do_cal( setup, current_cal, layout->dac_ground_observable( setup, channel, range ),
@@ -411,6 +424,39 @@ int generic_cal_by_range( calibration_setup_t *setup,
        return retval;
 }
 
+int generic_cal_ao(calibration_setup_t *setup,
+       const generic_layout_t *layout  )
+{
+       int channel, range, num_ao_ranges,
+               num_ao_channels, retval;
+       comedi_calibration_setting_t *current_cal;
+
+
+       if(setup->da_subdev && setup->do_output)
+       {
+               assert( comedi_range_is_chan_specific( setup->dev, setup->da_subdev ) == 0 );
+
+               num_ao_ranges = comedi_get_n_ranges( setup->dev, setup->da_subdev, 0 );
+               if( num_ao_ranges < 0 ) return -1;
+
+               num_ao_channels = comedi_get_n_channels( setup->dev, setup->da_subdev );
+               if( num_ao_channels < 0 ) return -1;
+       }else
+               num_ao_ranges = num_ao_channels = 0;
+       for( channel = 0; channel < num_ao_channels; channel++ )
+       {
+               for( range = 0; range < num_ao_ranges; range++ )
+               {
+                       current_cal = sc_alloc_calibration_setting( setup );
+                       generic_prep_dac_caldacs( setup, layout, channel, range );
+                       generic_do_dac_channel( setup, layout, setup->new_calibration,
+                               current_cal, channel, range );
+               }
+       }
+       retval = write_calibration_file( setup );
+       return retval;
+}
+
 static int dummy_caldac( unsigned int channel )
 {
        return -1;
@@ -429,11 +475,14 @@ void init_generic_layout( generic_layout_t *layout )
        layout->adc_postgain_offset = dummy_caldac;
        layout->dac_offset = dummy_caldac;
        layout->dac_offset_fine = dummy_caldac;
+       layout->dac_linearity = dummy_caldac;
+       layout->dac_linearity_fine = dummy_caldac;
        layout->dac_gain = dummy_caldac;
        layout->dac_gain_fine = dummy_caldac;
        layout->adc_high_observable = dummy_observable;
        layout->adc_ground_observable = dummy_observable;
        layout->dac_high_observable = dummy_observable;
+       layout->dac_mid_observable = dummy_observable;
        layout->dac_ground_observable = dummy_observable;
        layout->adc_fractional_tolerance = INFINITY;
        layout->adc_fractional_tolerance = INFINITY;
index 23a10d2226bbc01d551bb148edc5391c51efff2e..fdd584f1ac32562537d8b9a569c90d74cb030cca 100644 (file)
@@ -51,9 +51,7 @@ typedef struct{
 
        comedi_insn observe_insn;
 
-       //comedi_range *range;
-       //int maxdata;
-       lsampl_t reference_source;
+       int reference_source;
        double target;
 }observable;
 
@@ -244,6 +242,8 @@ typedef struct
        int (*adc_postgain_offset)( unsigned int channel );
        int (*adc_gain)( unsigned int channel );
        int (*adc_gain_fine)( unsigned int channel );
+       int (*dac_linearity)( unsigned int channel );
+       int (*dac_linearity_fine)( unsigned int channel );
        int (*dac_offset)( unsigned int channel );
        int (*dac_offset_fine)( unsigned int channel );
        int (*dac_gain)( unsigned int channel );
@@ -254,6 +254,8 @@ typedef struct
                unsigned int channel, unsigned int range );
        int (*dac_high_observable)( const calibration_setup_t *setup,
                unsigned int channel, unsigned int range );
+       int (*dac_mid_observable)( const calibration_setup_t *setup,
+               unsigned int channel, unsigned int range );
        int (*dac_ground_observable)( const calibration_setup_t *setup,
                unsigned int channel, unsigned int range );
        double adc_fractional_tolerance;
@@ -265,6 +267,8 @@ int generic_cal_by_channel_and_range( calibration_setup_t *setup,
        const generic_layout_t *layout  );
 int generic_cal_by_range( calibration_setup_t *setup,
        const generic_layout_t *layout  );
+int generic_cal_ao(calibration_setup_t *setup,
+       const generic_layout_t *layout  );
 void generic_do_cal( calibration_setup_t *setup,
        comedi_calibration_setting_t *saved_cal, int observable, int caldac );
 void generic_do_relative( calibration_setup_t *setup,
index 8ef2b99ada88b8ce1e09bd43ac4940022416b73e..54cf1e1365f2f6623a4369e6c9e003d6a6d85e1e 100644 (file)
@@ -319,7 +319,7 @@ ok:
        return retval;
 }
 
-void set_target( calibration_setup_t *setup, int obs,double target)
+void set_target( calibration_setup_t *setup, int obs, double target)
 {
        comedi_range *range;
        lsampl_t maxdata, data;
@@ -397,19 +397,22 @@ int preobserve( calibration_setup_t *setup, int obs)
        lsampl_t ref_data[ 2 ];
 
        // setup reference source
-       memset( &reference_source_config, 0, sizeof(reference_source_config) );
-       reference_source_config.insn = INSN_CONFIG;
-       reference_source_config.n = 2;
-       reference_source_config.subdev = setup->ad_subdev;
-       reference_source_config.data = ref_data;
-       reference_source_config.data[ 0 ] = INSN_CONFIG_ALT_SOURCE;
-       reference_source_config.data[ 1 ] = setup->observables[obs].reference_source;
-
-       retval = comedi_do_insn( setup->dev, &reference_source_config );
-       /* ignore errors for now since older ni driver doesn't
-        * support reference config insn */
-       if( retval < 0 )
-               perror("preobserve() ignoring reference config error" );
+       if(setup->observables[obs].reference_source >= 0)
+       {
+               memset( &reference_source_config, 0, sizeof(reference_source_config) );
+               reference_source_config.insn = INSN_CONFIG;
+               reference_source_config.n = 2;
+               reference_source_config.subdev = setup->ad_subdev;
+               reference_source_config.data = ref_data;
+               reference_source_config.data[ 0 ] = INSN_CONFIG_ALT_SOURCE;
+               reference_source_config.data[ 1 ] = setup->observables[obs].reference_source;
+
+               retval = comedi_do_insn( setup->dev, &reference_source_config );
+               /* ignore errors for now since older ni driver doesn't
+               * support reference config insn */
+               if( retval < 0 )
+                       perror("preobserve() ignoring reference config error" );
+       }
        retval = 0;
 
        if( setup->observables[obs].preobserve_insn.n != 0){
@@ -914,9 +917,10 @@ void setup_caldacs( calibration_setup_t *setup, int caldac_subdev )
        }
 
        // XXX check subdevice type is really calibration
-       // XXX check we dont exceed max number of allowable caldacs
 
        n_chan = comedi_get_n_channels( setup->dev, caldac_subdev );
+       assert(n_chan >= 0);
+       assert(setup->n_caldacs + n_chan < N_CALDACS);
 
        for(i = 0; i < n_chan; i++){
                setup->caldacs[ setup->n_caldacs + i ].subdev = caldac_subdev;
@@ -1461,7 +1465,7 @@ int linear_fit_monotonic(linear_fit_t *l)
                l->sxx+=x*x;
        }
        sxp=l->sxx-l->sx*l->sx/l->s1;
-       
+
        l->ave_x=l->sx/l->s1;
        l->ave_y=l->sy/l->s1;
        l->slope=(l->s1*l->sxy-l->sx*l->sy)/(l->s1*l->sxx-l->sx*l->sx);
index 496894ff9c685aa4d3c67fd9bfb8302234f92fe3..d8f74f4d1e75cba7c290c24438d9b665ecee4f50 100644 (file)
@@ -47,6 +47,7 @@ struct board_struct{
 static int ni_setup_board( calibration_setup_t *setup , const char *device_name );
 static void ni_setup_observables( calibration_setup_t *setup );
 static void ni_setup_observables_611x( calibration_setup_t *setup );
+static void ni67xx_setup_observables( calibration_setup_t *setup );
 
 static int cal_ni_at_mio_16e_2(calibration_setup_t *setup);
 static int cal_ni_daqcard_ai_16xe_50(calibration_setup_t *setup);
@@ -70,6 +71,7 @@ static int cal_ni_pci_611x(calibration_setup_t *setup);
 static int cal_ni_pci_mio_16e_4(calibration_setup_t *setup);
 static int cal_ni_daqcard_6062e(calibration_setup_t *setup);
 static int cal_ni_daqcard_6024e(calibration_setup_t *setup);
+static int cal_ni_pci_6711(calibration_setup_t *setup);
 
 static double ni_get_reference( calibration_setup_t *setup, int lsb_loc,int msb_loc);
 
@@ -110,10 +112,16 @@ static struct board_struct boards[]={
        { "pxi-6052e", STATUS_UNKNOWN, NULL, ni_setup_observables, -1, -1 },
        { "pxi-6070e", STATUS_UNKNOWN, NULL, ni_setup_observables, -1, -1 },
        { "pxi-6071e", STATUS_GUESS, cal_ni_pxi_6071e, ni_setup_observables, -1, -1 },
+       { "pci-6711", STATUS_GUESS, cal_ni_pci_6711, ni67xx_setup_observables, -1, -1},
+       { "pci-6713", STATUS_GUESS, cal_ni_pci_6711, ni67xx_setup_observables, -1, -1},
+       { "pci-6731", STATUS_GUESS, cal_ni_pci_6711, ni67xx_setup_observables, -1, -1},
+       { "pci-6733", STATUS_GUESS, cal_ni_pci_6711, ni67xx_setup_observables, -1, -1},
+       { "pxi-6711", STATUS_GUESS, cal_ni_pci_6711, ni67xx_setup_observables, -1, -1},
+       { "pxi-6713", STATUS_GUESS, cal_ni_pci_6711, ni67xx_setup_observables, -1, -1},
+       { "pxi-6731", STATUS_GUESS, cal_ni_pci_6711, ni67xx_setup_observables, -1, -1},
+       { "pxi-6733", STATUS_GUESS, cal_ni_pci_6711, ni67xx_setup_observables, -1, -1},
 #if 0
        { "at-mio-64e-3",       cal_ni_16e_1 },
-       { "pci-6711",           cal_ni_unknown },
-       { "pci-6713",           cal_ni_unknown },
 #endif
 };
 #define n_boards (sizeof(boards)/sizeof(boards[0]))
@@ -1362,3 +1370,149 @@ static double ni_get_reference( calibration_setup_t *setup, int lsb_loc,int msb_
        return ref;
 }
 
+/****************
+ NI 671x and 673x support
+ **************/
+
+static const int channels_per_ad8804 = 16;
+
+static inline int ni67xx_ao_gain_caldac(unsigned int ao_channel)
+{
+       int ad8804_gain_channels[4] = {8, 2, 11, 5};
+       int caldac_channel = ad8804_gain_channels[ao_channel % 4];
+       int caldac_index = ao_channel / 4;
+       /* just guessing that second ad8804 is works for ao channels 4-7
+        * the same as the first ad8804 works for ao channels 0-3 */
+       return caldac_index * channels_per_ad8804 + caldac_channel;
+}
+static inline int ni67xx_ao_linearity_caldac(unsigned int ao_channel)
+{
+       int ad8804_linearity_channels[4] = {4, 10, 1, 0};
+       int caldac_channel = ad8804_linearity_channels[ao_channel % 4];
+       int caldac_index = ao_channel / 4;
+
+       return caldac_index * channels_per_ad8804 + caldac_channel;
+}
+static inline int ni67xx_ao_offset_caldac(unsigned int ao_channel)
+{
+       int ad8804_offset_channels[4] = {7, 6, 9, 3};
+       int caldac_channel = ad8804_offset_channels[ao_channel % 4];
+       int caldac_index = ao_channel / 4;
+
+       return caldac_index * channels_per_ad8804 + caldac_channel;
+}
+
+static int ni67xx_ao_ground_observable_index( const calibration_setup_t *setup,
+       unsigned int channel, unsigned int ao_range )
+{
+       return 3 * channel;
+}
+
+static int ni67xx_ao_mid_observable_index( const calibration_setup_t *setup,
+       unsigned int channel, unsigned int ao_range )
+{
+       return 3 * channel + 1;
+}
+
+static int ni67xx_ao_high_observable_index( const calibration_setup_t *setup,
+       unsigned int channel, unsigned int ao_range )
+{
+       return 3 * channel + 2;
+}
+
+/* calibration adc uses RANGE_UNKNOWN, so it will return a value from
+   0.0 to 1.0 instead of a voltage, so we need to renormalize. */
+void ni67xx_set_target( calibration_setup_t *setup, int obs,double target)
+{
+       static const double reference = 5.0;
+
+       set_target(setup, obs, target);
+       /* calibration adc is roughly +=10V range, and inverted */
+       setup->observables[obs].target *= -1.0 / (reference * 4.0);
+       setup->observables[obs].target += 0.5;
+}
+
+static void ni67xx_setup_observables( calibration_setup_t *setup )
+{
+       comedi_insn tmpl, po_tmpl;
+       observable *o;
+       int num_ao_channels;
+       int i;
+
+       /* calibration adc is very slow (15HZ) but accurate, so only sample a few times */
+       setup->sv_order = 1;
+
+       num_ao_channels = comedi_get_n_channels(setup->dev, setup->da_subdev);
+       assert(num_ao_channels >= 0);
+
+       memset( &tmpl, 0, sizeof(tmpl) );
+       tmpl.insn = INSN_READ;
+       tmpl.n = 1;
+       tmpl.subdev = setup->ad_subdev;
+
+       memset( &po_tmpl, 0, sizeof(po_tmpl) );
+       po_tmpl.insn = INSN_WRITE;
+       po_tmpl.n = 1;
+       po_tmpl.subdev = setup->da_subdev;
+
+       setup->n_observables = 0;
+
+       for(i = 0; i < num_ao_channels; i++)
+       {
+               o = setup->observables + ni67xx_ao_ground_observable_index( setup,
+                       i, 0);
+               o->reference_source = -1;
+               assert( o->name == NULL );
+               asprintf(&o->name, "dac%i ground, ground referenced", i);
+               o->preobserve_insn = po_tmpl;
+               o->preobserve_insn.chanspec = CR_PACK(i, 0, AREF_GROUND);
+               o->preobserve_insn.data = o->preobserve_data;
+               o->observe_insn = tmpl;
+               o->observe_insn.chanspec = CR_PACK(i, 0, AREF_GROUND);
+               ni67xx_set_target(setup, ni67xx_ao_ground_observable_index(setup, i, 0), 0.0);
+               setup->n_observables++;
+
+               o = setup->observables + ni67xx_ao_mid_observable_index( setup,
+                       i, 0);
+               o->reference_source = -1;
+               assert( o->name == NULL );
+               asprintf(&o->name, "dac%i mid, ground referenced", i);
+               o->preobserve_insn = po_tmpl;
+               o->preobserve_insn.chanspec = CR_PACK(i, 0, AREF_GROUND);
+               o->preobserve_insn.data = o->preobserve_data;
+               o->observe_insn = tmpl;
+               o->observe_insn.chanspec = CR_PACK(i, 0, AREF_GROUND);
+               ni67xx_set_target(setup, ni67xx_ao_mid_observable_index(setup, i, 0), 4.0);
+               setup->n_observables++;
+
+               o = setup->observables + ni67xx_ao_high_observable_index( setup, i, 0);
+               o->reference_source = -1;
+               assert( o->name == NULL );
+               asprintf(&o->name, "dac%i high, ground referenced", i);
+               o->preobserve_insn = po_tmpl;
+               o->preobserve_insn.chanspec = CR_PACK( i, 0, AREF_GROUND );
+               o->preobserve_insn.data = o->preobserve_data;
+               o->observe_insn = tmpl;
+               o->observe_insn.chanspec = CR_PACK(i, 0, AREF_GROUND);
+               ni67xx_set_target(setup, ni67xx_ao_high_observable_index(setup, i, 0), 8.0);
+               setup->n_observables++;
+       }
+
+       return;
+}
+
+static int cal_ni_pci_6711(calibration_setup_t *setup)
+{
+       generic_layout_t layout;
+
+       init_generic_layout( &layout );
+       layout.dac_gain = ni67xx_ao_gain_caldac;
+       layout.dac_linearity = ni67xx_ao_linearity_caldac;
+       layout.dac_offset = ni67xx_ao_offset_caldac;
+       layout.dac_high_observable = ni67xx_ao_high_observable_index;
+       layout.dac_mid_observable = ni67xx_ao_mid_observable_index;
+       layout.dac_ground_observable = ni67xx_ao_ground_observable_index;
+       layout.dac_fractional_tolerance = get_tolerance( setup, setup->da_subdev, 1.0 );
+       return generic_cal_ao(setup, &layout);
+}
+