From c3551c8cccdba3f8ba626e85d3694cd59e30e40f Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Fri, 2 May 2003 21:58:23 +0000 Subject: [PATCH] added 'write to file' support for ni 611x boards, and calibration of all their input ranges. --- comedi_calibrate/Makefile.am | 2 +- comedi_calibrate/cal_common.c | 206 +++++++++++++++ comedi_calibrate/calib.h | 31 ++- comedi_calibrate/cb.c | 1 - comedi_calibrate/cb64.c | 91 ++----- comedi_calibrate/comedi_calibrate.c | 4 +- comedi_calibrate/ni.c | 393 ++++++++++++++-------------- 7 files changed, 447 insertions(+), 281 deletions(-) create mode 100644 comedi_calibrate/cal_common.c diff --git a/comedi_calibrate/Makefile.am b/comedi_calibrate/Makefile.am index 1e7e4fe..0acc161 100644 --- a/comedi_calibrate/Makefile.am +++ b/comedi_calibrate/Makefile.am @@ -4,7 +4,7 @@ bin_PROGRAMS = comedi_calibrate noinst_HEADERS = calib.h comedi_calibrate_SOURCES = \ - comedi_calibrate.c ni.c cb.c cb64.c other.c save_cal.c + comedi_calibrate.c ni.c cb.c cb64.c other.c save_cal.c cal_common.c comedi_calibrate_CFLAGS = $(COMEDILIB_CFLAGS) comedi_calibrate_LDADD = $(COMEDILIB_LIBS) diff --git a/comedi_calibrate/cal_common.c b/comedi_calibrate/cal_common.c new file mode 100644 index 0000000..c0454f1 --- /dev/null +++ b/comedi_calibrate/cal_common.c @@ -0,0 +1,206 @@ +/*************************************************************************** + cal_common.c - shared calibration routines + ------------------- + + begin : Fri May 2, 2003 + copyright : (C) 2003 by Frank Mori Hess + email : fmhess@users.sourceforge.net + + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License as * + * published by * + * the Free Software Foundation; either version 2.1 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "calib.h" +#include +#include + +void generic_do_cal( calibration_setup_t *setup, + saved_calibration_t *saved_cal, int observable, int caldac ) +{ + if( caldac < 0 || observable < 0 ) return; + + cal_binary( setup, observable, caldac ); + sc_push_caldac( saved_cal, setup->caldacs[ caldac ] ); +} + +void generic_do_relative( calibration_setup_t *setup, + saved_calibration_t *saved_cal, int observable1, int observable2, int caldac ) +{ + if( caldac < 0 || observable1 < 0 || observable2 < 0 ) return; + + cal_relative_binary( setup, observable1, observable2, caldac ); + sc_push_caldac( saved_cal, setup->caldacs[ caldac ] ); +} + +void generic_do_linearity( calibration_setup_t *setup, + saved_calibration_t *saved_cal, int observable1, int observable2, + int observable3, int caldac ) +{ + if( caldac < 0 || observable1 < 0 || observable2 < 0 || observable3 < 0 ) + return; + + cal_linearity_binary( setup, observable1, observable2, observable3, caldac ); + sc_push_caldac( saved_cal, setup->caldacs[ caldac ] ); +} + +void generic_prep_adc_caldacs( calibration_setup_t *setup, + const generic_layout_t *layout, unsigned int channel, unsigned int range ) +{ + int retval; + + if( setup->ad_subdev < 0 ) return; + + if( setup->do_reset ) + { + reset_caldac( setup, layout->adc_offset( channel ) ); + reset_caldac( setup, layout->adc_gain( channel ) ); + }else + { + retval = comedi_apply_calibration( setup->dev, setup->ad_subdev, + channel, range, AREF_GROUND, setup->cal_save_file_path); + if( retval < 0 ) + { + DPRINT( 0, "Failed to apply existing calibration, reseting dac caldacs.\n" ); + reset_caldac( setup, layout->adc_offset( channel ) ); + reset_caldac( setup, layout->adc_gain( channel ) ); + } + } +} + +void generic_prep_dac_caldacs( calibration_setup_t *setup, + const generic_layout_t *layout, unsigned int channel, unsigned int range ) +{ + int retval; + + if( setup->da_subdev < 0 ) return; + + if( setup->do_reset ) + { + reset_caldac( setup, layout->dac_offset( channel ) ); + reset_caldac( setup, layout->dac_gain( channel ) ); + }else + { + retval = comedi_apply_calibration( setup->dev, setup->da_subdev, + channel, range, AREF_GROUND, setup->cal_save_file_path); + if( retval < 0 ) + { + 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 ) ); + } + } +} + +int generic_cal_by_channel_and_range( calibration_setup_t *setup, + const generic_layout_t *layout ) +{ + int range, channel, num_ai_ranges, num_ai_channels, num_ao_ranges, + num_ao_channels, retval, num_calibrations, i; + saved_calibration_t *saved_cals, *current_cal; + + assert( comedi_range_is_chan_specific( setup->dev, setup->ad_subdev ) == 0 ); + + num_ai_ranges = comedi_get_n_ranges( setup->dev, setup->ad_subdev, 0 ); + if( num_ai_ranges < 0 ) return -1; + + num_ai_channels = comedi_get_n_channels( setup->dev, setup->ad_subdev ); + if( num_ai_channels < 0 ) return -1; + + 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; + + num_calibrations = num_ai_ranges * num_ai_channels + num_ao_ranges * num_ao_channels; + + saved_cals = malloc( num_calibrations * sizeof( saved_calibration_t ) ); + if( saved_cals == NULL ) return -1; + + current_cal = saved_cals; + + for( channel = 0; channel < num_ai_channels; channel++ ) + { + for( range = 0; range < num_ai_ranges; range++ ) + { + generic_prep_adc_caldacs( setup, layout, channel, range ); + + generic_do_cal( setup, current_cal, layout->adc_ground_observable( channel, range ), + layout->adc_offset( channel ) ); + + generic_do_cal( setup, current_cal, layout->adc_high_observable( channel, range ), + layout->adc_gain( channel ) ); + + current_cal->subdevice = setup->ad_subdev; + sc_push_caldac( current_cal, setup->caldacs[ layout->adc_gain( channel ) ] ); + sc_push_caldac( current_cal, setup->caldacs[ layout->adc_offset( channel ) ] ); + sc_push_channel( current_cal, channel ); + sc_push_range( current_cal, range ); + sc_push_aref( current_cal, SC_ALL_AREFS ); + + current_cal++; + } + } + for( channel = 0; channel < num_ao_channels; channel++ ) + { + for( range = 0; range < num_ao_ranges; range++ ) + { + generic_prep_dac_caldacs( setup, layout, channel, range ); + + generic_do_cal( setup, current_cal, layout->dac_ground_observable( channel, range ), + layout->dac_offset( channel ) ); + + generic_do_cal( setup, current_cal, layout->dac_high_observable( channel, range ), + layout->dac_gain( channel ) ); + + current_cal->subdevice = setup->da_subdev; + sc_push_caldac( current_cal, setup->caldacs[ layout->dac_gain( channel ) ] ); + sc_push_caldac( current_cal, setup->caldacs[ layout->dac_offset( channel ) ] ); + sc_push_channel( current_cal, channel ); + sc_push_range( current_cal, range ); + sc_push_aref( current_cal, SC_ALL_AREFS ); + + current_cal++; + } + } + + retval = write_calibration_file( setup, saved_cals, num_calibrations ); + for( i = 0; i < num_calibrations; i++ ) + clear_saved_calibration( &saved_cals[ i ] ); + free( saved_cals ); + return retval; +} + +static int dummy_caldac( unsigned int channel ) +{ + return -1; +} +static int dummy_observable( unsigned int channel, unsigned int range ) +{ + return -1; +} +void init_generic_layout( generic_layout_t *layout ) +{ + layout->adc_offset = dummy_caldac; + layout->adc_gain = dummy_caldac; + layout->dac_offset = dummy_caldac; + layout->dac_gain = dummy_caldac; + layout->adc_high_observable = dummy_observable; + layout->adc_ground_observable = dummy_observable; + layout->dac_high_observable = dummy_observable; + layout->dac_ground_observable = dummy_observable; +} diff --git a/comedi_calibrate/calib.h b/comedi_calibrate/calib.h index 5de512a..0038982 100644 --- a/comedi_calibrate/calib.h +++ b/comedi_calibrate/calib.h @@ -11,7 +11,7 @@ #ifndef __CALIB_H_ #define __CALIB_H_ -#include +#include "comedilib.h" #if 0 #include #include @@ -93,7 +93,7 @@ void observe( calibration_setup_t *setup ); int preobserve( calibration_setup_t *setup, int obs); void observable_dependence( calibration_setup_t *setup, int obs); void measure_observable( calibration_setup_t *setup, int obs); -void reset_caldac( calibration_setup_t *setup, unsigned int caldac_index ); +void reset_caldac( calibration_setup_t *setup, int caldac_index ); void reset_caldacs( calibration_setup_t *setup); /* drivers */ @@ -246,5 +246,32 @@ void sc_push_range( saved_calibration_t *saved_cal, int range ); void sc_push_aref( saved_calibration_t *saved_cal, int aref ); void clear_saved_calibration( saved_calibration_t *saved_cal ); +/* generic calibration support */ +typedef struct +{ + int (*adc_offset)( unsigned int channel ); + int (*adc_gain)( unsigned int channel ); + int (*dac_offset)( unsigned int channel ); + int (*dac_gain)( unsigned int channel ); + int (*adc_high_observable)( unsigned int channel, unsigned int range ); + int (*adc_ground_observable)( unsigned int channel, unsigned int range ); + int (*dac_high_observable)( unsigned int channel, unsigned int range ); + int (*dac_ground_observable)( unsigned int channel, unsigned int range ); +} generic_layout_t; +void init_generic_layout( generic_layout_t *layout ); +int generic_cal_by_channel_and_range( calibration_setup_t *setup, + const generic_layout_t *layout ); +void generic_do_cal( calibration_setup_t *setup, + saved_calibration_t *saved_cal, int observable, int caldac ); +void generic_do_relative( calibration_setup_t *setup, + saved_calibration_t *saved_cal, int observable1, int observable2, int caldac ); +void generic_do_linearity( calibration_setup_t *setup, + saved_calibration_t *saved_cal, int observable1, int observable2, + int observable3, int caldac ); +void generic_prep_adc_caldacs( calibration_setup_t *setup, + const generic_layout_t *layout, unsigned int channel, unsigned int range ); +void generic_prep_dac_caldacs( calibration_setup_t *setup, + const generic_layout_t *layout, unsigned int channel, unsigned int range ); + #endif diff --git a/comedi_calibrate/cb.c b/comedi_calibrate/cb.c index 78bd5a4..15dcb49 100644 --- a/comedi_calibrate/cb.c +++ b/comedi_calibrate/cb.c @@ -21,7 +21,6 @@ #define _GNU_SOURCE #include -#include #include #include #include diff --git a/comedi_calibrate/cb64.c b/comedi_calibrate/cb64.c index e64f9d7..7a17896 100644 --- a/comedi_calibrate/cb64.c +++ b/comedi_calibrate/cb64.c @@ -21,7 +21,6 @@ #define _GNU_SOURCE #include -#include "comedilib.h" #include #include #include @@ -128,15 +127,6 @@ enum cal_knobs_64xx ADC_OFFSET_64XX = 9, }; -static inline unsigned int ADC_OFFSET_4020( unsigned int channel ) -{ - return channel; -} -static inline unsigned int ADC_GAIN_4020( unsigned int channel ) -{ - return 4 + channel; -} - int cb64_setup( calibration_setup_t *setup, const char *device_name ) { unsigned int i; @@ -615,13 +605,13 @@ static int init_observables_60xx( calibration_setup_t *setup ) return 0; } -static unsigned int ai_low_observable_index_4020( unsigned int channel, +static int ai_low_observable_index_4020( unsigned int channel, unsigned int ai_range ) { return 4 * channel + 2 * ai_range; } -static unsigned int ai_high_observable_index_4020( unsigned int channel, +static int ai_high_observable_index_4020( unsigned int channel, unsigned int ai_range ) { return ai_low_observable_index_4020( channel, ai_range ) + 1; @@ -1032,73 +1022,24 @@ static int cal_cb_pci_60xx( calibration_setup_t *setup ) return retval; } -static void prep_adc_caldacs_4020( calibration_setup_t *setup, - unsigned int channel, unsigned int range ) +static int adc_offset_4020( unsigned int channel ) { - int retval; - - if( setup->do_reset ) - { - reset_caldac( setup, ADC_OFFSET_4020( channel ) ); - reset_caldac( setup, ADC_GAIN_4020( channel ) ); - }else - { - retval = comedi_apply_calibration( setup->dev, setup->ad_subdev, - channel, range, AREF_GROUND, setup->cal_save_file_path); - if( retval < 0 ) - { - reset_caldac( setup, ADC_OFFSET_4020( channel ) ); - reset_caldac( setup, ADC_GAIN_4020( channel ) ); - } - } + return channel; +} +static int adc_gain_4020( unsigned int channel ) +{ + return 4 + channel; } static int cal_cb_pci_4020( calibration_setup_t *setup ) { - int range, channel, num_ranges, num_channels, retval, - num_calibrations, i; - saved_calibration_t *saved_cals, *current_cal; - - num_ranges = comedi_get_n_ranges( setup->dev, setup->ad_subdev, 0 ); - if( num_ranges < 0 ) return -1; - - num_channels = comedi_get_n_channels( setup->dev, setup->ad_subdev ); - if( num_channels < 0 ) return -1; - - num_calibrations = num_ranges * num_channels; - - saved_cals = malloc( num_calibrations * sizeof( saved_calibration_t ) ); - if( saved_cals == NULL ) return -1; - - current_cal = saved_cals; - - for( channel = 0; channel < num_channels; channel++ ) - { - for( range = 0; range < num_ranges; range++ ) - { - prep_adc_caldacs_4020( setup, channel, range ); - - cal_binary( setup, ai_low_observable_index_4020( channel, range ), - ADC_OFFSET_4020( channel ) ); - - cal_binary( setup, ai_high_observable_index_4020( channel, range ), - ADC_GAIN_4020( channel ) ); - - current_cal->subdevice = setup->ad_subdev; - sc_push_caldac( current_cal, setup->caldacs[ ADC_GAIN_4020( channel ) ] ); - sc_push_caldac( current_cal, setup->caldacs[ ADC_OFFSET_4020( channel ) ] ); - sc_push_channel( current_cal, channel ); - sc_push_range( current_cal, range ); - sc_push_aref( current_cal, SC_ALL_AREFS ); - - current_cal++; - } - } - - retval = write_calibration_file( setup, saved_cals, num_calibrations ); - for( i = 0; i < num_calibrations; i++ ) - clear_saved_calibration( &saved_cals[ i ] ); - free( saved_cals ); - return retval; + generic_layout_t layout; + + init_generic_layout( &layout ); + layout.adc_offset = adc_offset_4020; + layout.adc_gain = adc_gain_4020; + layout.adc_high_observable = ai_high_observable_index_4020; + layout.adc_ground_observable = ai_low_observable_index_4020; + return generic_cal_by_channel_and_range( setup, &layout ); } diff --git a/comedi_calibrate/comedi_calibrate.c b/comedi_calibrate/comedi_calibrate.c index c913ab5..5b3d858 100644 --- a/comedi_calibrate/comedi_calibrate.c +++ b/comedi_calibrate/comedi_calibrate.c @@ -786,9 +786,10 @@ void setup_caldacs( calibration_setup_t *setup, int caldac_subdev ) setup->n_caldacs += n_chan; } -void reset_caldac( calibration_setup_t *setup, unsigned int caldac_index ) +void reset_caldac( calibration_setup_t *setup, int caldac_index ) { assert( caldac_index < setup->n_caldacs ); + if( caldac_index < 0 ) return; update_caldac( setup, caldac_index, setup->caldacs[ caldac_index ].maxdata / 2 ); } @@ -1442,3 +1443,4 @@ double very_low_target( comedi_t *dev, unsigned int subdevice, return comedi_to_phys( 1, range_ptr, max_data ) / 2.0; } + diff --git a/comedi_calibrate/ni.c b/comedi_calibrate/ni.c index aa39058..03728de 100644 --- a/comedi_calibrate/ni.c +++ b/comedi_calibrate/ni.c @@ -26,7 +26,6 @@ #define _GNU_SOURCE #include -#include "comedilib.h" #include #include #include @@ -173,17 +172,20 @@ static inline unsigned int ni_ao_unip_linearity( unsigned int channel ) else return ni_ao0_unip_linearity; } -enum observables_611x{ - ni_ao0_zero_offset_611x = 0, - ni_ao0_reference_611x = 1, - ni_ao1_zero_offset_611x = 2, - ni_ao1_reference_611x = 3, +static const int num_ao_observables_611x = 4; +static int ni_ao_zero_offset_611x( unsigned int channel, unsigned int range ) { + assert( range = 0 ); + return 2 * channel; }; -static inline unsigned int ni_zero_offset_611x( unsigned int channel ) { - return 4 + 2 * channel; +static int ni_ao_reference_611x( unsigned int channel, unsigned int range ) { + assert( range = 0 ); + return 2 * channel + 1; }; -static inline unsigned int ni_reference_611x( unsigned int channel ) { - return 5 + 2 * channel; +static int ni_zero_offset_611x( unsigned int channel, unsigned int range ) { + return num_ao_observables_611x + 8 * range + 2 * channel; +}; +static int ni_reference_611x( unsigned int channel, unsigned int range ) { + return num_ao_observables_611x + 8 * range + 2 * channel + 1; }; enum reference_sources { @@ -490,7 +492,7 @@ static void ni_setup_observables( calibration_setup_t *setup ) ni_setup_ao_observables( setup ); } -/* XXX for +-50V and +-20V ranges, the reference source goes 0V +/* for +-50V and +-20V ranges, the reference source goes 0V * to 50V instead of 0V to 5V */ static unsigned int cal_gain_register_bits_611x( double reference, double *voltage ) { @@ -508,52 +510,76 @@ static unsigned int ref_source_611x( unsigned int ref_source, unsigned int cal_g return ( ref_source & 0xf ) | ( ( cal_gain_bits << 4 ) & 0xff0 ); } +static void reference_target_611x( calibration_setup_t *setup, + observable *o, double master_reference, unsigned int range ) +{ + int cal_gain_reg_bits; + double reference; + double target; + comedi_range *range_ptr; + + range_ptr = comedi_get_range( setup->dev, setup->ad_subdev, 0, range ); + assert( range_ptr != NULL ); + if( range_ptr->max > 19.0 ) reference = 10 * master_reference; + else reference = master_reference; + target = range_ptr->max * 0.9; + + cal_gain_reg_bits = cal_gain_register_bits_611x( reference, &target ); + + o->reference_source = ref_source_611x( REF_CALSRC_GND, cal_gain_reg_bits ); + o->target = target; +} + static void ni_setup_observables_611x( calibration_setup_t *setup ) { comedi_insn tmpl; comedi_insn po_tmpl; - int range, ai_range_for_ao; - double voltage_reference, master_reference; + int range, channel; + double master_reference; observable *o; - int ai_chan; - int num_chans; - int cal_gain_reg_bits; + int num_ai_channels, num_ai_ranges; + static const int num_ao_channels = 2; setup->settling_time_ns = 1000000; - range = 2; - master_reference = ni_get_reference( setup, ni_board( setup )->ref_eeprom_lsb, ni_board( setup )->ref_eeprom_msb ); - voltage_reference = 5.0; - cal_gain_reg_bits = cal_gain_register_bits_611x( master_reference, &voltage_reference ); memset(&tmpl,0,sizeof(tmpl)); tmpl.insn = INSN_READ; tmpl.n = 1; tmpl.subdev = setup->ad_subdev; - num_chans = comedi_get_n_channels( setup->dev, setup->ad_subdev ); + num_ai_channels = comedi_get_n_channels( setup->dev, setup->ad_subdev ); + assert( num_ai_channels >= 0 ); + num_ai_ranges = comedi_get_n_ranges( setup->dev, setup->ad_subdev, 0 ); + assert( num_ai_ranges >= 0 ); - for( ai_chan = 0; ai_chan < num_chans; ai_chan++ ) + for( channel = 0; channel < num_ai_channels; channel++ ) { - /* 0 offset */ - o = setup->observables + ni_zero_offset_611x( ai_chan ); - o->name = "ai, bipolar zero offset"; - o->observe_insn = tmpl; - o->observe_insn.chanspec = CR_PACK(ai_chan, range, AREF_DIFF) - | CR_ALT_SOURCE | CR_ALT_FILTER; - o->reference_source = REF_GND_GND; - o->target = 0.0; + for( range = 0; range < num_ai_ranges; range++ ) + { + /* 0 offset */ + o = setup->observables + ni_zero_offset_611x( channel, range ); + assert( o->name == NULL ); + asprintf( &o->name, "ai, ch %i, range %i, zero offset", + channel, range ); + o->observe_insn = tmpl; + o->observe_insn.chanspec = CR_PACK( channel, range, AREF_DIFF ) + | CR_ALT_SOURCE | CR_ALT_FILTER; + o->reference_source = REF_GND_GND; + o->target = 0.0; - /* voltage reference */ - o = setup->observables + ni_reference_611x( ai_chan ); - o->name = "ai, bipolar voltage reference"; - o->observe_insn = tmpl; - o->observe_insn.chanspec = CR_PACK(ai_chan, range, AREF_DIFF) - | CR_ALT_SOURCE | CR_ALT_FILTER; - o->reference_source = ref_source_611x( REF_CALSRC_GND, cal_gain_reg_bits ); - o->target = voltage_reference; + /* voltage reference */ + o = setup->observables + ni_reference_611x( channel, range ); + assert( o->name == NULL ); + asprintf( &o->name, "ai, ch %i, range %i, voltage reference", + channel, range ); + o->observe_insn = tmpl; + o->observe_insn.chanspec = CR_PACK( channel, range, AREF_DIFF ) + | CR_ALT_SOURCE | CR_ALT_FILTER; + reference_target_611x( setup, o, master_reference, range ); + } } memset(&po_tmpl,0,sizeof(po_tmpl)); @@ -561,57 +587,38 @@ static void ni_setup_observables_611x( calibration_setup_t *setup ) po_tmpl.n = 1; po_tmpl.subdev = setup->da_subdev; - ai_range_for_ao = 2; + for( channel = 0; channel < num_ao_channels; channel ++ ) + { + static const int ai_range_for_ao = 2; - /* ao 0, zero offset */ - o = setup->observables + ni_ao0_zero_offset_611x; - o->name = "ao 0, zero offset"; - o->preobserve_insn = po_tmpl; - o->preobserve_insn.chanspec = CR_PACK( 0, 0, AREF_GROUND ); - o->preobserve_insn.data = o->preobserve_data; - o->observe_insn = tmpl; - o->observe_insn.chanspec = CR_PACK( 0, ai_range_for_ao, AREF_DIFF ) - | CR_ALT_SOURCE | CR_ALT_FILTER; - o->reference_source = REF_DAC0_GND; - set_target( setup, ni_ao0_zero_offset_611x, 0.0 ); - - /* ao 0, gain */ - o = setup->observables + ni_ao0_reference_611x; - o->name = "ao 0, reference voltage"; - o->preobserve_insn = po_tmpl; - o->preobserve_insn.chanspec = CR_PACK( 0, 0, AREF_GROUND ); - o->preobserve_insn.data = o->preobserve_data; - o->observe_insn = tmpl; - o->observe_insn.chanspec = CR_PACK( 0, ai_range_for_ao, AREF_DIFF ) - | CR_ALT_SOURCE | CR_ALT_FILTER; - o->reference_source = REF_DAC0_GND; - set_target( setup, ni_ao0_reference_611x, 5.0 ); - - /* ao 1, zero offset */ - o = setup->observables + ni_ao1_zero_offset_611x; - o->name = "ao 1, zero offset"; - o->preobserve_insn = po_tmpl; - o->preobserve_insn.chanspec = CR_PACK( 1, 0, AREF_GROUND ); - o->preobserve_insn.data = o->preobserve_data; - o->observe_insn = tmpl; - o->observe_insn.chanspec = CR_PACK( 0, ai_range_for_ao, AREF_DIFF) - | CR_ALT_SOURCE | CR_ALT_FILTER; - o->reference_source = REF_DAC1_GND; - set_target( setup, ni_ao1_zero_offset_611x, 0.0 ); - - /* ao 1, gain */ - o = setup->observables + ni_ao1_reference_611x; - o->name = "ao 1, reference voltage"; - o->preobserve_insn = po_tmpl; - o->preobserve_insn.chanspec = CR_PACK( 1, 0, AREF_GROUND ); - o->preobserve_insn.data = o->preobserve_data; - o->observe_insn = tmpl; - o->observe_insn.chanspec = CR_PACK( 0, ai_range_for_ao, AREF_DIFF ) - | CR_ALT_SOURCE | CR_ALT_FILTER; - o->reference_source = REF_DAC1_GND; - set_target( setup, ni_ao1_reference_611x, 5.0 ); + /* ao zero offset */ + o = setup->observables + ni_ao_zero_offset_611x( channel, 0 ); + assert( o->name == NULL ); + asprintf( &o->name, "ao ch %i, zero offset", channel ); + o->preobserve_insn = po_tmpl; + o->preobserve_insn.chanspec = CR_PACK( channel, 0, AREF_GROUND ); + o->preobserve_insn.data = o->preobserve_data; + o->observe_insn = tmpl; + o->observe_insn.chanspec = CR_PACK( 0, ai_range_for_ao, AREF_DIFF ) + | CR_ALT_SOURCE | CR_ALT_FILTER; + o->reference_source = REF_DAC0_GND; + set_target( setup, ni_ao_zero_offset_611x( channel, 0 ), 0.0 ); - setup->n_observables = 4 + 2 * num_chans; + /* ao gain */ + o = setup->observables + ni_ao_reference_611x( channel, 0 ); + assert( o->name == NULL ); + asprintf( &o->name, "ao ch %i, reference voltage", channel ); + o->preobserve_insn = po_tmpl; + o->preobserve_insn.chanspec = CR_PACK( channel, 0, AREF_GROUND ); + o->preobserve_insn.data = o->preobserve_data; + o->observe_insn = tmpl; + o->observe_insn.chanspec = CR_PACK( 0, ai_range_for_ao, AREF_DIFF ) + | CR_ALT_SOURCE | CR_ALT_FILTER; + o->reference_source = REF_DAC0_GND; + set_target( setup, ni_ao_reference_611x( channel, 0 ), 5.0 ); + } + + setup->n_observables = num_ao_observables_611x + 2 * num_ai_ranges * num_ai_channels; } static int cal_ni_at_mio_16e_2(calibration_setup_t *setup) @@ -890,34 +897,41 @@ static int cal_ni_pci_6052e(calibration_setup_t *setup) /* * This board has noisy caldacs * - * The NI documentation says: - * 0, 8 AI pregain (coarse, fine) 3, 11 - * 4, 12 AI postgain 15,7 - * 2, 10 AI reference 1, 9 - * 14, 7 AI unipolar offset 5, 13 + * The NI documentation says (true mb88341 addressing): + * 0, 8 AI pregain (coarse, fine) + * 4, 12 AI postgain + * 2, 10 AI reference + * 14, 7 AI unipolar offset * * 0 AO0 linearity - * 8, 4 AO0 reference 23, 19 7, 3 - * 12 AO0 offset 27 11 + * 8, 4 AO0 reference + * 12 AO0 offset * 2 AO1 linearity - * 10, 6 AO1 reference 25, 21 9, 5 - * 14 AO1 offset 29, 17 13, 1 - * - * 0 3 x 0011 - * - * 2 1 x 0001 + * 10, 6 AO1 reference + * 14 AO1 offset * - * 4 7 15 3 0111 0011 + * For us, these map to (ad8804 channels) * - * 6 17 5 0101 - * 7 x - * 8 11 19 7 1011 0111 + * 0, 1 AI pregain (coarse, fine) + * 2, 3 AI postgain + * 4, 5 AI reference + * 7 AI unipolar offset * - * 10 9 21 9 1001 1001 + * 0 AO0 linearity + * 1, 2 AO0 reference + * 3 AO0 offset + * 4 AO1 linearity + * 5, 6 AO1 reference + * 7 AO1 offset * - * 12 x 23 11 1011 + * or, with mb88341 channels * - * 14 5 13 1 0101 0001 + * xxx AO0 linearity + * 7, 3 AO0 reference + * 11 AO0 offset + * 1 AO1 linearity + * 9, 5 AO1 reference + * xxx AO1 offset * */ ni_caldac_layout_t layout; @@ -966,26 +980,37 @@ static int cal_ni_daqcard_ai_16e_4(calibration_setup_t *setup) return cal_ni_generic( setup, &layout ); } +static int adc_offset_611x( unsigned int channel ) +{ + return 2 * channel + 2; +} +static int adc_gain_611x( unsigned int channel ) +{ + return 2 * channel + 1; +} +static int dac_offset_611x( unsigned int channel ) +{ + return 12 + 2 + 2 * channel; +} +static int dac_gain_611x( unsigned int channel ) +{ + return 12 + 1 + 2 * channel; +} static int cal_ni_pci_611x( calibration_setup_t *setup ) { - int i; - int num_chans; - - num_chans = comedi_get_n_channels( setup->dev, setup->ad_subdev ); - - for( i = 0; i < num_chans; i++ ){ - cal_binary( setup, ni_zero_offset_611x( i ), ( 2 * i + 2 ) ); - cal_binary( setup, ni_reference_611x( i ), ( 2 * i + 1 ) ); - } - - if(setup->do_output){ - cal_binary( setup, ni_ao0_zero_offset_611x, 14 ); - cal_binary( setup, ni_ao0_reference_611x, 13 ); - cal_binary( setup, ni_ao1_zero_offset_611x, 16 ); - cal_binary( setup, ni_ao1_reference_611x, 15 ); - } - - return 0; + generic_layout_t layout; + + init_generic_layout( &layout ); + layout.adc_offset = adc_offset_611x; + layout.adc_gain = adc_gain_611x; + layout.dac_offset = dac_offset_611x; + layout.dac_gain = dac_gain_611x; + layout.adc_high_observable = ni_reference_611x; + layout.adc_ground_observable = ni_zero_offset_611x; + layout.dac_high_observable = ni_ao_reference_611x; + layout.dac_ground_observable = ni_ao_zero_offset_611x; + + return generic_cal_by_channel_and_range( setup, &layout ); } static int cal_ni_pci_mio_16e_4( calibration_setup_t *setup ) @@ -1026,13 +1051,6 @@ static int cal_ni_daqcard_6062e( calibration_setup_t *setup ) return cal_ni_generic( setup, &layout ); } -static void ni_generic_reset_caldac( calibration_setup_t *setup, - int caldac ) -{ - if( caldac < 0 ) return; - reset_caldac( setup, caldac ); -} - static void prep_adc_caldacs_generic( calibration_setup_t *setup, const ni_caldac_layout_t *layout ) { @@ -1040,13 +1058,13 @@ static void prep_adc_caldacs_generic( calibration_setup_t *setup, if( setup->do_reset ) { - ni_generic_reset_caldac( setup, layout->adc_pregain_offset ); - ni_generic_reset_caldac( setup, layout->adc_postgain_offset ); - ni_generic_reset_caldac( setup, layout->adc_gain ); - ni_generic_reset_caldac( setup, layout->adc_pregain_offset_fine ); - ni_generic_reset_caldac( setup, layout->adc_postgain_offset_fine ); - ni_generic_reset_caldac( setup, layout->adc_gain_fine ); - ni_generic_reset_caldac( setup, layout->adc_unip_offset ); + reset_caldac( setup, layout->adc_pregain_offset ); + reset_caldac( setup, layout->adc_postgain_offset ); + reset_caldac( setup, layout->adc_gain ); + reset_caldac( setup, layout->adc_pregain_offset_fine ); + reset_caldac( setup, layout->adc_postgain_offset_fine ); + reset_caldac( setup, layout->adc_gain_fine ); + reset_caldac( setup, layout->adc_unip_offset ); }else { retval = comedi_apply_calibration( setup->dev, setup->ad_subdev, @@ -1054,19 +1072,19 @@ static void prep_adc_caldacs_generic( calibration_setup_t *setup, if( retval < 0 ) { DPRINT( 0, "Failed to apply existing calibration, reseting adc caldacs.\n" ); - ni_generic_reset_caldac( setup, layout->adc_pregain_offset ); - ni_generic_reset_caldac( setup, layout->adc_postgain_offset ); - ni_generic_reset_caldac( setup, layout->adc_gain ); - ni_generic_reset_caldac( setup, layout->adc_pregain_offset_fine ); - ni_generic_reset_caldac( setup, layout->adc_postgain_offset_fine ); - ni_generic_reset_caldac( setup, layout->adc_gain_fine ); - ni_generic_reset_caldac( setup, layout->adc_unip_offset ); + reset_caldac( setup, layout->adc_pregain_offset ); + reset_caldac( setup, layout->adc_postgain_offset ); + reset_caldac( setup, layout->adc_gain ); + reset_caldac( setup, layout->adc_pregain_offset_fine ); + reset_caldac( setup, layout->adc_postgain_offset_fine ); + reset_caldac( setup, layout->adc_gain_fine ); + reset_caldac( setup, layout->adc_unip_offset ); } } } static void prep_dac_caldacs_generic( calibration_setup_t *setup, - const ni_caldac_layout_t *layout, unsigned int channel ) + const ni_caldac_layout_t *layout, unsigned int channel, unsigned int range ) { int retval; @@ -1074,53 +1092,25 @@ static void prep_dac_caldacs_generic( calibration_setup_t *setup, if( setup->do_reset ) { - ni_generic_reset_caldac( setup, layout->dac_offset[ channel ] ); - ni_generic_reset_caldac( setup, layout->dac_gain[ channel ] ); - ni_generic_reset_caldac( setup, layout->dac_gain_fine[ channel ] ); - ni_generic_reset_caldac( setup, layout->dac_linearity[ channel ] ); + reset_caldac( setup, layout->dac_offset[ channel ] ); + reset_caldac( setup, layout->dac_gain[ channel ] ); + reset_caldac( setup, layout->dac_gain_fine[ channel ] ); + reset_caldac( setup, layout->dac_linearity[ channel ] ); }else { retval = comedi_apply_calibration( setup->dev, setup->da_subdev, - channel, 0, AREF_GROUND, setup->cal_save_file_path); + channel, range, AREF_GROUND, setup->cal_save_file_path); if( retval < 0 ) { DPRINT( 0, "Failed to apply existing calibration, reseting dac caldacs.\n" ); - ni_generic_reset_caldac( setup, layout->dac_offset[ channel ] ); - ni_generic_reset_caldac( setup, layout->dac_gain[ channel ] ); - ni_generic_reset_caldac( setup, layout->dac_gain_fine[ channel ] ); - ni_generic_reset_caldac( setup, layout->dac_linearity[ channel ] ); + reset_caldac( setup, layout->dac_offset[ channel ] ); + reset_caldac( setup, layout->dac_gain[ channel ] ); + reset_caldac( setup, layout->dac_gain_fine[ channel ] ); + reset_caldac( setup, layout->dac_linearity[ channel ] ); } } } -static void ni_generic_binary( calibration_setup_t *setup, - saved_calibration_t *saved_cal, int observable, int caldac ) -{ - if( caldac < 0 ) return; - - cal_binary( setup, observable, caldac ); - sc_push_caldac( saved_cal, setup->caldacs[ caldac ] ); -} - -static void ni_generic_relative( calibration_setup_t *setup, - saved_calibration_t *saved_cal, int observable1, int observable2, int caldac ) -{ - if( caldac < 0 ) return; - - cal_relative_binary( setup, observable1, observable2, caldac ); - sc_push_caldac( saved_cal, setup->caldacs[ caldac ] ); -} - -static void ni_generic_linearity( calibration_setup_t *setup, - saved_calibration_t *saved_cal, int observable1, int observable2, - int observable3, int caldac ) -{ - if( caldac < 0 ) return; - - cal_linearity_binary( setup, observable1, observable2, observable3, caldac ); - sc_push_caldac( saved_cal, setup->caldacs[ caldac ] ); -} - static int cal_ni_generic( calibration_setup_t *setup, const ni_caldac_layout_t *layout ) { saved_calibration_t saved_cals[ 5 ], *current_cal; @@ -1134,18 +1124,18 @@ static int cal_ni_generic( calibration_setup_t *setup, const ni_caldac_layout_t prep_adc_caldacs_generic( setup, layout ); current_cal->subdevice = setup->ad_subdev; - ni_generic_relative( setup, current_cal, ni_zero_offset_low, + generic_do_relative( setup, current_cal, ni_zero_offset_low, ni_reference_low, layout->adc_gain ); - ni_generic_relative( setup, current_cal, ni_zero_offset_low, + generic_do_relative( setup, current_cal, ni_zero_offset_low, ni_zero_offset_high, layout->adc_postgain_offset ); - ni_generic_binary( setup, current_cal, ni_zero_offset_high, layout->adc_pregain_offset ); - ni_generic_relative( setup, current_cal, ni_zero_offset_low, + generic_do_cal( setup, current_cal, ni_zero_offset_high, layout->adc_pregain_offset ); + generic_do_relative( setup, current_cal, ni_zero_offset_low, ni_reference_low, layout->adc_gain_fine ); - ni_generic_relative( setup, current_cal, ni_zero_offset_low, + generic_do_relative( setup, current_cal, ni_zero_offset_low, ni_zero_offset_high, layout->adc_postgain_offset_fine ); - ni_generic_binary( setup, current_cal, ni_zero_offset_high, + generic_do_cal( setup, current_cal, ni_zero_offset_high, layout->adc_pregain_offset_fine ); - ni_generic_binary( setup, current_cal, ni_unip_zero_offset_high, layout->adc_unip_offset ); + generic_do_cal( setup, current_cal, ni_unip_zero_offset_high, layout->adc_unip_offset ); sc_push_channel( current_cal, SC_ALL_CHANNELS ); sc_push_range( current_cal, SC_ALL_RANGES ); sc_push_aref( current_cal, SC_ALL_AREFS ); @@ -1155,22 +1145,23 @@ static int cal_ni_generic( calibration_setup_t *setup, const ni_caldac_layout_t { unsigned int channel, range; int ao_unipolar_lowgain = get_unipolar_lowgain( setup->dev, setup->da_subdev ); + int ao_bipolar_lowgain = get_bipolar_lowgain( setup->dev, setup->da_subdev ); int num_ao_ranges; for( channel = 0; channel < 2; channel++ ) { num_ao_ranges = comedi_get_n_ranges( setup->dev, setup->da_subdev, channel ); - prep_dac_caldacs_generic( setup, layout, channel ); + prep_dac_caldacs_generic( setup, layout, channel, ao_bipolar_lowgain ); current_cal->subdevice = setup->da_subdev; - ni_generic_linearity( setup, current_cal, ni_ao_linearity( channel ), + generic_do_linearity( setup, current_cal, ni_ao_linearity( channel ), ni_ao_zero_offset( channel ), ni_ao_reference( channel ), layout->dac_linearity[ channel ] ); - ni_generic_binary( setup, current_cal, ni_ao_zero_offset( channel ), + generic_do_cal( setup, current_cal, ni_ao_zero_offset( channel ), layout->dac_offset[ channel ] ); - ni_generic_binary( setup, current_cal, ni_ao_reference( channel ), + generic_do_cal( setup, current_cal, ni_ao_reference( channel ), layout->dac_gain[ channel ] ); - ni_generic_binary( setup, current_cal, ni_ao_reference( channel ), + generic_do_cal( setup, current_cal, ni_ao_reference( channel ), layout->dac_gain_fine[ channel ] ); sc_push_channel( current_cal, channel ); for( range = 0; range < num_ao_ranges; range++ ) @@ -1183,17 +1174,17 @@ static int cal_ni_generic( calibration_setup_t *setup, const ni_caldac_layout_t if( ao_unipolar_lowgain >= 0 ) { - prep_dac_caldacs_generic( setup, layout, channel ); + prep_dac_caldacs_generic( setup, layout, channel, ao_unipolar_lowgain ); current_cal->subdevice = setup->da_subdev; - ni_generic_linearity( setup, current_cal, ni_ao_unip_zero_offset( channel ), + generic_do_linearity( setup, current_cal, ni_ao_unip_zero_offset( channel ), ni_ao_unip_linearity( channel ), ni_ao_unip_reference( channel ), layout->dac_linearity[ channel ] ); - ni_generic_binary( setup, current_cal, ni_ao_unip_zero_offset( channel), + generic_do_cal( setup, current_cal, ni_ao_unip_zero_offset( channel), layout->dac_offset[ channel ] ); - ni_generic_binary( setup, current_cal, ni_ao_unip_reference( channel ), + generic_do_cal( setup, current_cal, ni_ao_unip_reference( channel ), layout->dac_gain[ channel ] ); - ni_generic_binary( setup, current_cal, ni_ao_unip_reference( channel ), + generic_do_cal( setup, current_cal, ni_ao_unip_reference( channel ), layout->dac_gain_fine[ channel ] ); sc_push_channel( current_cal, channel ); for( range = 0; range < num_ao_ranges; range++ ) -- 2.26.2