* (at your option) any later version. *
* *
***************************************************************************/
+#define _GNU_SOURCE
#include "calib.h"
#include <assert.h>
#include <stdlib.h>
+#include <math.h>
void generic_do_cal( calibration_setup_t *setup,
comedi_calibration_setting_t *saved_cal, int observable, int caldac )
adc_channel, adc_range, 0, calibration );
}
+static int dac_cal_is_good( calibration_setup_t *setup, const generic_layout_t *layout,
+ unsigned int channel, unsigned int range )
+{
+ if( fabs( fractional_offset( setup, setup->da_subdev, channel, range,
+ layout->dac_ground_observable( setup, channel, range ) ) ) > layout->dac_fractional_tolerance )
+ return 0;
+ else if( fabs( fractional_offset( setup, setup->da_subdev, channel, range,
+ layout->dac_high_observable( setup, channel, range ) ) ) > layout->dac_fractional_tolerance )
+ return 0;
+
+ return 1;
+}
+
static void generic_do_dac_channel( calibration_setup_t *setup, const generic_layout_t *layout ,
comedi_calibration_t *calibration, comedi_calibration_setting_t *current_cal,
unsigned int channel, unsigned int range )
{
+ static const int max_iterations = 4;
+ int i;
+
generic_prep_adc_for_dac( setup, layout, calibration,
layout->dac_ground_observable( setup, channel, range ) );
- 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_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 ),
- layout->dac_offset_fine( channel ) );
-
+ for( i = 0; i < max_iterations; i++ )
+ {
+ 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_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 ),
+ layout->dac_offset_fine( channel ) );
+ if( dac_cal_is_good( setup, layout, channel, range ) ) break;
+ }
+ if( i == max_iterations )
+ DPRINT(0, "WARNING: unable to calibrate dac channel %i, range %i to desired %g tolerance\n",
+ channel, range, layout->dac_fractional_tolerance );
current_cal->subdevice = setup->da_subdev;
sc_push_channel( current_cal, channel );
sc_push_range( current_cal, range );
sc_push_aref( current_cal, SC_ALL_AREFS );
}
+static int adc_cal_is_good( calibration_setup_t *setup, const generic_layout_t *layout,
+ unsigned int channel, unsigned int range )
+{
+ if( fabs( fractional_offset( setup, setup->ad_subdev, channel, range,
+ layout->adc_ground_observable( setup, channel, range ) ) ) > layout->adc_fractional_tolerance )
+ return 0;
+ else if( fabs( fractional_offset( setup, setup->ad_subdev, channel, range,
+ layout->adc_high_observable( setup, channel, range ) ) ) > layout->adc_fractional_tolerance )
+ return 0;
+
+ return 1;
+}
+
static void generic_do_adc_channel( calibration_setup_t *setup, const generic_layout_t *layout,
comedi_calibration_setting_t *current_cal, unsigned int channel, unsigned int range )
{
- /* make sure unipolar ground observable isn't out-of-range before
- * doing gain calibrations */
- if( is_unipolar( setup->dev, setup->ad_subdev, channel, range ) )
+ static const int max_iterations = 4;
+ int i;
+
+ for( i = 0; i < max_iterations; i++ )
{
+ generic_do_relative( setup, current_cal, layout->adc_high_observable( setup, channel, range ),
+ layout->adc_ground_observable( setup, channel, range ), layout->adc_gain( channel ) );
generic_do_cal( setup, current_cal, layout->adc_ground_observable( setup, channel, range ),
layout->adc_offset( channel ) );
+ generic_do_relative( setup, current_cal, layout->adc_high_observable( setup, channel, range ),
+ layout->adc_ground_observable( setup, channel, range ), layout->adc_gain_fine( channel ) );
generic_do_cal( setup, current_cal, layout->adc_ground_observable( setup, channel, range ),
layout->adc_offset_fine( channel ) );
+ if( adc_cal_is_good( setup, layout, channel, range ) ) break;
}
- generic_do_relative( setup, current_cal, layout->adc_high_observable( setup, channel, range ),
- layout->adc_ground_observable( setup, channel, range ), layout->adc_gain( channel ) );
- generic_do_cal( setup, current_cal, layout->adc_ground_observable( setup, channel, range ),
- layout->adc_offset( channel ) );
- generic_do_relative( setup, current_cal, layout->adc_high_observable( setup, channel, range ),
- layout->adc_ground_observable( setup, channel, range ), layout->adc_gain_fine( channel ) );
- generic_do_cal( setup, current_cal, layout->adc_ground_observable( setup, channel, range ),
- layout->adc_offset_fine( channel ) );
-
+ if( i == max_iterations )
+ DPRINT(0, "WARNING: unable to calibrate adc channel %i, range %i to desired %g tolerance\n",
+ channel, range, layout->adc_fractional_tolerance );
current_cal->subdevice = setup->ad_subdev;
sc_push_channel( current_cal, channel );
sc_push_range( current_cal, range );
layout->adc_ground_observable = dummy_observable;
layout->dac_high_observable = dummy_observable;
layout->dac_ground_observable = dummy_observable;
- layout->do_adc_unipolar_postgain = 1;
+ layout->adc_fractional_tolerance = INFINITY;
+ layout->adc_fractional_tolerance = INFINITY;
+ layout->do_adc_unipolar_postgain = 0;
}
static const int num_boards = ( sizeof(boards) / sizeof(boards[0]) );
-enum observables_1602_16 {
- OBS_0V_RANGE_10V_BIP_1602_16 = 0,
- OBS_7V_RANGE_10V_BIP_1602_16,
-};
-
enum calibration_source_1xxx
{
CS_1XXX_GROUND = 0,
DPRINT(0, "WARNING: you need comedi driver version 0.7.67 or later\n"
"for this calibration to work properly\n" );
}
-
+ setup->sv_settling_time_ns = 10000000;
+ setup->sv_order = 12;
retval = init_observables_1xxx( setup );
+
if( retval < 0 ) return retval;
setup_caldacs( setup, caldac_subdev );
setup_caldacs( setup, calpot_subdev );
layout.adc_ground_observable = ai_ground_observable_1xxx;
layout.dac_high_observable = ao_high_observable_1xxx;
layout.dac_ground_observable = ao_ground_observable_1xxx;
+ layout.adc_fractional_tolerance = get_tolerance( setup, setup->ad_subdev, 1 );
+ layout.dac_fractional_tolerance = get_tolerance( setup, setup->da_subdev, 1 );
return generic_cal_by_range( setup, &layout );
}
layout.adc_ground_observable = ai_ground_observable_1xxx;
layout.dac_high_observable = ao_high_observable_1xxx;
layout.dac_ground_observable = ao_ground_observable_1xxx;
+ layout.adc_fractional_tolerance = get_tolerance( setup, setup->ad_subdev, 1 );
+ layout.dac_fractional_tolerance = get_tolerance( setup, setup->da_subdev, 1 );
/* The bipolar postgain calibration should be good for both
* bipolar and unipolar ranges, so disable separate
* unipolar postgain offset calibration (it will fail