RTXI 1.3
comedi_calibrate/comedi_calibrate/cb.c
Go to the documentation of this file.
00001 /***************************************************************************
00002         cb.c  -  calibration support for some Measurement computing boards.
00003                            -------------------
00004 
00005     begin                : Sat Apr 27 2002
00006     copyright            : (C) 2002,2003 by Frank Mori Hess
00007     email                : fmhess@users.sourceforge.net
00008 
00009  ***************************************************************************/
00010 
00011 /***************************************************************************
00012  *                                                                         *
00013  *   This program is free software; you can redistribute it and/or modify  *
00014  *   it under the terms of the GNU Lesser General Public License as        *
00015  *   published by                                                          *
00016  *   the Free Software Foundation; either version 2.1 of the License, or   *
00017  *   (at your option) any later version.                                   *
00018  *                                                                         *
00019  ***************************************************************************/
00020 
00021 #define _GNU_SOURCE
00022 
00023 #include <stdio.h>
00024 #include <fcntl.h>
00025 #include <unistd.h>
00026 #include <errno.h>
00027 #include <getopt.h>
00028 #include <ctype.h>
00029 #include <math.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032 #include <stdint.h>
00033 #include <assert.h>
00034 
00035 #include "calib.h"
00036 
00037 
00038 char cb_id[] = "$Id: cb.c,v 1.1.1.1 2006-02-05 20:53:20 fmhess Exp $";
00039 
00040 struct board_struct{
00041         char *name;
00042         int status;
00043         int (*setup)( calibration_setup_t *setup );
00044 };
00045 
00046 static int setup_cb_pci_1xxx( calibration_setup_t *setup );
00047 static int setup_cb_pci_1602_16( calibration_setup_t *setup );
00048 
00049 static int cal_cb_pci_1xxx( calibration_setup_t *setup );
00050 static int cal_cb_pci_1602_16( calibration_setup_t *setup );
00051 
00052 static int init_observables_1xxx( calibration_setup_t *setup );
00053 
00054 static struct board_struct boards[]={
00055         { "pci-das1000",        STATUS_DONE,    setup_cb_pci_1xxx },
00056         { "pci-das1001",        STATUS_GUESS,   setup_cb_pci_1xxx },
00057         { "pci-das1002",        STATUS_GUESS,   setup_cb_pci_1xxx },
00058         { "pci-das1200",        STATUS_DONE,    setup_cb_pci_1xxx },
00059         { "pci-das1200/jr",     STATUS_GUESS,   setup_cb_pci_1xxx },
00060         { "pci-das1602/12",     STATUS_GUESS,   setup_cb_pci_1xxx },
00061         { "pci-das1602/16",     STATUS_DONE,    setup_cb_pci_1602_16 },
00062         { "pci-das1602/16/jr",  STATUS_GUESS,   setup_cb_pci_1602_16 },
00063 };
00064 
00065 static const int num_boards = ( sizeof(boards) / sizeof(boards[0]) );
00066 
00067 enum calibration_source_1xxx
00068 {
00069         CS_1XXX_GROUND = 0,
00070         CS_1XXX_7V = 1,
00071         CS_1002_3500mV = 2,
00072         CS_1002_1750mV = 3,
00073         CS_1001_88600uV = 3,
00074         CS_1XXX_875mV = 4,
00075         CS_1XXX_8600uV = 5,
00076         CS_1602_16_minus_10V = 5,
00077         CS_1XXX_DAC0 = 6,
00078         CS_1XXX_DAC1 = 7,
00079 };
00080 static inline int CS_1XXX_DAC( unsigned int channel )
00081 {
00082         if( channel )
00083                 return CS_1XXX_DAC1;
00084         else
00085                 return CS_1XXX_DAC0;
00086 }
00087 
00088 int cb_setup( calibration_setup_t *setup, const char *device_name )
00089 {
00090         unsigned int i;
00091 
00092         for( i = 0; i < num_boards; i++ )
00093         {
00094                 if( !strcmp( device_name, boards[i].name ) )
00095                 {
00096                         setup->status = boards[i].status;
00097                         return boards[i].setup( setup );
00098                         break;
00099                 }
00100         }
00101         if( i == num_boards ) return -1;
00102 
00103         return 0;
00104 }
00105 
00106 static int setup_cb_pci_1xxx( calibration_setup_t *setup )
00107 {
00108         int retval;
00109         static const int caldac_subdev = 4;
00110         static const int calpot_subdev = 5;
00111 
00112         if( comedi_get_version_code( setup->dev ) <= COMEDI_VERSION_CODE( 0, 7, 66 ) )
00113         {
00114                 DPRINT(0, "WARNING: you need comedi driver version 0.7.67 or later\n"
00115                  "for this calibration to work properly\n" );
00116         }
00117         //this larger delay is definitely needed by pci-das1000, possibly not for pci-das1200
00118         setup->sv_settling_time_ns = 10000000;
00119         retval = init_observables_1xxx( setup );
00120         if( retval < 0 ) return retval;
00121         setup_caldacs( setup, caldac_subdev );
00122         setup_caldacs( setup, calpot_subdev );
00123         setup->do_cal = cal_cb_pci_1xxx;
00124         return 0;
00125 }
00126 
00127 static int setup_cb_pci_1602_16( calibration_setup_t *setup )
00128 {
00129         int retval;
00130         static const int caldac_subdev = 4;
00131         static const int calpot_subdev = 5;
00132         static const int dac08_subdev = 6;
00133 
00134         if( comedi_get_version_code( setup->dev ) <= COMEDI_VERSION_CODE( 0, 7, 66 ) )
00135         {
00136                 DPRINT(0, "WARNING: you need comedi driver version 0.7.67 or later\n"
00137                  "for this calibration to work properly\n" );
00138         }
00139         setup->sv_settling_time_ns = 10000000;
00140         setup->sv_order = 12;
00141         retval = init_observables_1xxx( setup );
00142 
00143         if( retval < 0 ) return retval;
00144         setup_caldacs( setup, caldac_subdev );
00145         setup_caldacs( setup, calpot_subdev );
00146         setup_caldacs( setup, dac08_subdev );
00147         setup->do_cal = cal_cb_pci_1602_16;
00148         return 0;
00149 }
00150 
00151 static int ai_ground_observable_1xxx( const calibration_setup_t *setup,
00152         unsigned int channel, unsigned int range )
00153 {
00154         return 2 * range;
00155 }
00156 
00157 static int ai_high_observable_1xxx( const calibration_setup_t *setup,
00158         unsigned int channel, unsigned int range )
00159 {
00160         return ai_ground_observable_1xxx( setup, channel, range ) + 1;
00161 }
00162 
00163 static int ao_ground_observable_1xxx( const calibration_setup_t *setup,
00164         unsigned int channel, unsigned int range )
00165 {
00166         int num_ai_ranges, num_ao_ranges;
00167 
00168         num_ai_ranges = comedi_get_n_ranges( setup->dev, setup->ad_subdev, 0 );
00169         assert( num_ai_ranges > 0 );
00170         num_ao_ranges = comedi_get_n_ranges( setup->dev, setup->da_subdev, 0 );
00171         assert( num_ao_ranges > 0 );
00172 
00173         return 2 * num_ai_ranges + 2 * num_ao_ranges * channel + 2 * range;
00174 }
00175 
00176 static int ao_high_observable_1xxx( const calibration_setup_t *setup,
00177         unsigned int channel, unsigned int range )
00178 {
00179         return ao_ground_observable_1xxx( setup, channel, range ) + 1;
00180 }
00181 
00182 static double ai_low_target_1xxx( calibration_setup_t *setup,
00183         unsigned int range )
00184 {
00185         if( is_bipolar( setup->dev, setup->ad_subdev, 0, range ) )
00186                 return 0.0;
00187         else
00188                 return very_low_target( setup->dev, setup->ad_subdev, 0, range );
00189 }
00190 
00191 static int source_eeprom_addr_1xxx( calibration_setup_t *setup, unsigned int range_index )
00192 {
00193         enum source_eeprom_addr
00194         {
00195                 EEPROM_7V_CHAN = 0x80,
00196                 EEPROM_3500mV_CHAN = 0x84,
00197                 EEPROM_1750mV_CHAN = 0x88,
00198                 EEPROM_88600uV_CHAN_1001 = 0x88,
00199                 EEPROM_875mV_CHAN = 0x8c,
00200                 EEPROM_8600uV_CHAN = 0x90,
00201         };
00202         comedi_range *range;
00203 
00204         range = comedi_get_range( setup->dev, setup->ad_subdev, 0, range_index );
00205         if( range == NULL ) return -1;
00206 
00207         if( range->max > 7.0 )
00208                 return EEPROM_7V_CHAN;
00209         else if( range->max > 3.5 )
00210                 return EEPROM_3500mV_CHAN;
00211         else if( range->max > 1.750 )
00212                 return EEPROM_1750mV_CHAN;
00213         else if( range->max > 0.875 )
00214                 return EEPROM_875mV_CHAN;
00215         else if( range->max > .0886 )
00216                 return EEPROM_88600uV_CHAN_1001;
00217         else if( range->max > 0.0086 )
00218                 return EEPROM_8600uV_CHAN;
00219 
00220         return -1;
00221 }
00222 
00223 static int ai_high_cal_source_1xxx( calibration_setup_t *setup, unsigned int range_index )
00224 {
00225         comedi_range *range;
00226 
00227         range = comedi_get_range( setup->dev, setup->ad_subdev, 0, range_index );
00228         if( range == NULL ) return -1;
00229 
00230         if( range->max > 7.0 )
00231                 return CS_1XXX_7V;
00232         else if( range->max > 3.5 )
00233                 return CS_1002_3500mV;
00234         else if( range->max > 1.750 )
00235                 return CS_1002_1750mV;
00236         else if( range->max > 0.875 )
00237                 return CS_1XXX_875mV;
00238         else if( range->max > .0886 )
00239                 return CS_1001_88600uV;
00240         else if( range->max > 0.0086 )
00241                 return CS_1XXX_8600uV;
00242 
00243         return -1;
00244 }
00245 
00246 static int ao_set_high_target_1xxx( calibration_setup_t *setup, unsigned int obs,
00247         unsigned int range_index )
00248 {
00249         double target;
00250         comedi_range *range;
00251 
00252         range = comedi_get_range( setup->dev, setup->da_subdev, 0, range_index );
00253         if( range == NULL ) return -1;
00254 
00255         target = range->max * 0.9;
00256         set_target( setup, obs, target );
00257         return 0;
00258 }
00259 
00260 static int init_observables_1xxx( calibration_setup_t *setup )
00261 {
00262         comedi_insn tmpl, po_tmpl;
00263         observable *o;
00264         int retval, range, num_ai_ranges, num_ao_ranges,
00265                 channel, num_channels;
00266         float target;
00267         int ai_for_ao_range;
00268 
00269         setup->n_observables = 0;
00270 
00271         memset( &tmpl, 0, sizeof(tmpl) );
00272         tmpl.insn = INSN_READ;
00273         tmpl.n = 1;
00274         tmpl.subdev = setup->ad_subdev;
00275 
00276         num_ai_ranges = comedi_get_n_ranges( setup->dev, setup->ad_subdev, 0 );
00277         if( num_ai_ranges < 0 ) return -1;
00278 
00279         for( range = 0; range < num_ai_ranges; range++ )
00280         {
00281                 o = setup->observables + ai_ground_observable_1xxx( setup, 0, range );
00282                 o->reference_source = CS_1XXX_GROUND;
00283                 assert( o->name == NULL );
00284                 asprintf( &o->name, "calibration source %i, range %i, ground referenced",
00285                         o->reference_source, range );
00286                 o->observe_insn = tmpl;
00287                 o->observe_insn.chanspec = CR_PACK( 0, range, AREF_GROUND) |
00288                         CR_ALT_SOURCE | CR_ALT_FILTER;
00289                 o->target = ai_low_target_1xxx( setup, range );
00290                 setup->n_observables++;
00291 
00292                 o = setup->observables + ai_high_observable_1xxx( setup, 0, range );;
00293                 retval = ai_high_cal_source_1xxx( setup, range );
00294                 if( retval < 0 ) return -1;
00295                 o->reference_source = retval;
00296                 assert( o->name == NULL );
00297                 asprintf( &o->name, "calibration source %i, range %i, ground referenced",
00298                         o->reference_source, range );
00299                 o->observe_insn = tmpl;
00300                 o->observe_insn.chanspec = CR_PACK( 0, range, AREF_GROUND) |
00301                         CR_ALT_SOURCE | CR_ALT_FILTER;
00302                 retval = cb_actual_source_voltage( setup->dev, setup->eeprom_subdev,
00303                         source_eeprom_addr_1xxx( setup, range ), &target );
00304                 if( retval < 0 ) return -1;
00305                 o->target = target;
00306                 setup->n_observables++;
00307         }
00308 
00309         if( setup->da_subdev >= 0 )
00310         {
00311                 num_channels = comedi_get_n_channels( setup->dev, setup->da_subdev );
00312                 if( num_channels < 0 ) return -1;
00313 
00314                 num_ao_ranges = comedi_get_n_ranges( setup->dev, setup->da_subdev, 0 );
00315                 if( num_ao_ranges < 0 ) return -1;
00316 
00317                 memset( &po_tmpl, 0, sizeof(po_tmpl) );
00318                 po_tmpl.insn = INSN_WRITE;
00319                 po_tmpl.n = 1;
00320                 po_tmpl.subdev = setup->da_subdev;
00321 
00322                 ai_for_ao_range = get_bipolar_lowgain( setup->dev, setup->ad_subdev );
00323                 if( ai_for_ao_range < 0 ) return -1;
00324 
00325                 for( range = 0; range < num_ao_ranges; range++ )
00326                 {
00327                         for( channel = 0; channel < num_channels; channel++ )
00328                         {
00329                                 o = setup->observables + ao_ground_observable_1xxx( setup, channel, range );
00330                                 o->reference_source = CS_1XXX_DAC( channel );
00331                                 assert( o->name == NULL );
00332                                 asprintf( &o->name, "DAC ground calibration source, ch %i, range %i",
00333                                         channel, range );
00334                                 o->preobserve_insn = po_tmpl;
00335                                 o->preobserve_insn.chanspec = CR_PACK( channel, range, AREF_GROUND );
00336                                 o->preobserve_insn.data = o->preobserve_data;
00337                                 o->observe_insn = tmpl;
00338                                 o->observe_insn.chanspec = CR_PACK( 0, ai_for_ao_range, AREF_GROUND) |
00339                                         CR_ALT_SOURCE | CR_ALT_FILTER;
00340                                 set_target( setup, ao_ground_observable_1xxx( setup, channel, range ), 0.0 );
00341                                 setup->n_observables++;
00342 
00343                                 o = setup->observables + ao_high_observable_1xxx( setup, channel, range );
00344                                 o->reference_source = CS_1XXX_DAC( channel );
00345                                 assert( o->name == NULL );
00346                                 asprintf( &o->name, "DAC high calibration source, ch %i, range %i", channel,
00347                                         range );
00348                                 o->preobserve_insn = po_tmpl;
00349                                 o->preobserve_insn.chanspec = CR_PACK( channel , range, AREF_GROUND );
00350                                 o->preobserve_insn.data = o->preobserve_data;
00351                                 o->observe_insn = tmpl;
00352                                 o->observe_insn.chanspec = CR_PACK( 0, ai_for_ao_range, AREF_GROUND) |
00353                                         CR_ALT_SOURCE | CR_ALT_FILTER;
00354                                 ao_set_high_target_1xxx( setup, ao_high_observable_1xxx( setup, channel, range ),
00355                                         range );
00356                                 setup->n_observables++;
00357                         }
00358                 }
00359         }
00360 
00361         return 0;
00362 }
00363 
00364 enum cal_knobs_1xxx
00365 {
00366         DAC0_GAIN_FINE_1XXX = 0,
00367         DAC0_GAIN_COARSE_1XXX = 1,
00368         DAC0_OFFSET_1XXX = 2,
00369         DAC1_OFFSET_1XXX = 3,
00370         DAC1_GAIN_FINE_1XXX = 4,
00371         DAC1_GAIN_COARSE_1XXX = 5,
00372         ADC_OFFSET_COARSE_1XXX = 6,
00373         ADC_OFFSET_FINE_1XXX = 7,
00374         ADC_GAIN_1XXX = 8,
00375 };
00376 static int adc_offset_coarse_1xxx( unsigned int channel )
00377 {
00378         return ADC_OFFSET_COARSE_1XXX;
00379 }
00380 static int adc_offset_fine_1xxx( unsigned int channel )
00381 {
00382         return ADC_OFFSET_FINE_1XXX;
00383 }
00384 static int adc_gain_1xxx( unsigned int channel )
00385 {
00386         return ADC_GAIN_1XXX;
00387 }
00388 static int dac_offset_1xxx( unsigned int channel )
00389 {
00390         if( channel )
00391                 return DAC1_OFFSET_1XXX;
00392         else
00393                 return DAC0_OFFSET_1XXX;
00394 }
00395 static int dac_gain_fine_1xxx( unsigned int channel )
00396 {
00397         if( channel )
00398                 return DAC1_GAIN_FINE_1XXX;
00399         else
00400                 return DAC0_GAIN_FINE_1XXX;
00401 }
00402 static int dac_gain_coarse_1xxx( unsigned int channel )
00403 {
00404         if( channel )
00405                 return DAC1_GAIN_COARSE_1XXX;
00406         else
00407                 return DAC0_GAIN_COARSE_1XXX;
00408 }
00409 
00410 static int cal_cb_pci_1xxx( calibration_setup_t *setup )
00411 {
00412         generic_layout_t layout;
00413 
00414         init_generic_layout( &layout );
00415         layout.adc_gain = adc_gain_1xxx;
00416         layout.adc_offset = adc_offset_coarse_1xxx;
00417         layout.adc_offset_fine = adc_offset_fine_1xxx;
00418         layout.dac_gain = dac_gain_coarse_1xxx;
00419         layout.dac_gain_fine = dac_gain_fine_1xxx;
00420         layout.dac_offset = dac_offset_1xxx;
00421         layout.adc_high_observable = ai_high_observable_1xxx;
00422         layout.adc_ground_observable = ai_ground_observable_1xxx;
00423         layout.dac_high_observable = ao_high_observable_1xxx;
00424         layout.dac_ground_observable = ao_ground_observable_1xxx;
00425         layout.adc_fractional_tolerance = get_tolerance( setup, setup->ad_subdev, 1.0 );
00426         layout.dac_fractional_tolerance = get_tolerance( setup, setup->da_subdev, 1.0 );
00427         return generic_cal_by_range( setup, &layout );
00428 }
00429 
00430 enum cal_knobs_1602_16
00431 {
00432         DAC0_GAIN_FINE_1602_16 = 0,
00433         DAC0_GAIN_COARSE_1602_16 = 1,
00434         DAC0_OFFSET_COARSE_1602_16 = 2,
00435         DAC1_OFFSET_COARSE_1602_16 = 3,
00436         DAC1_GAIN_FINE_1602_16 = 4,
00437         DAC1_GAIN_COARSE_1602_16 = 5,
00438         DAC0_OFFSET_FINE_1602_16 = 6,
00439         DAC1_OFFSET_FINE_1602_16 = 7,
00440         ADC_GAIN_1602_16 = 8,
00441         ADC_POSTGAIN_OFFSET_1602_16 = 9,
00442         ADC_PREGAIN_OFFSET_1602_16 = 10,
00443 };
00444 static int dac_gain_coarse_1602_16( unsigned int channel )
00445 {
00446         if( channel ) return DAC1_GAIN_COARSE_1602_16;
00447         else return DAC0_GAIN_COARSE_1602_16;
00448 }
00449 static int dac_gain_fine_1602_16( unsigned int channel )
00450 {
00451         if( channel ) return DAC1_GAIN_FINE_1602_16;
00452         else return DAC0_GAIN_FINE_1602_16;
00453 }
00454 static int dac_offset_coarse_1602_16( unsigned int channel )
00455 {
00456         if( channel ) return DAC1_OFFSET_COARSE_1602_16;
00457         else return DAC0_OFFSET_COARSE_1602_16;
00458 }
00459 static int dac_offset_fine_1602_16( unsigned int channel )
00460 {
00461         if( channel ) return DAC1_OFFSET_FINE_1602_16;
00462         else return DAC0_OFFSET_FINE_1602_16;
00463 }
00464 static int adc_gain_1602_16( unsigned int channel )
00465 {
00466         return ADC_GAIN_1602_16;
00467 }
00468 static int adc_pregain_offset_1602_16( unsigned int channel )
00469 {
00470         return ADC_PREGAIN_OFFSET_1602_16;
00471 }
00472 static int adc_postgain_offset_1602_16( unsigned int channel )
00473 {
00474         return ADC_POSTGAIN_OFFSET_1602_16;
00475 }
00476 static int cal_cb_pci_1602_16( calibration_setup_t *setup )
00477 {
00478         generic_layout_t layout;
00479 
00480         init_generic_layout( &layout );
00481         layout.adc_gain = adc_gain_1602_16;
00482         layout.adc_offset = adc_pregain_offset_1602_16;
00483         layout.adc_postgain_offset = adc_postgain_offset_1602_16;
00484         layout.dac_gain = dac_gain_coarse_1602_16;
00485         layout.dac_gain_fine = dac_gain_fine_1602_16;
00486         layout.dac_offset = dac_offset_coarse_1602_16;
00487         layout.dac_offset_fine = dac_offset_fine_1602_16;
00488         layout.adc_high_observable = ai_high_observable_1xxx;
00489         layout.adc_ground_observable = ai_ground_observable_1xxx;
00490         layout.dac_high_observable = ao_high_observable_1xxx;
00491         layout.dac_ground_observable = ao_ground_observable_1xxx;
00492         layout.adc_fractional_tolerance = get_tolerance( setup, setup->ad_subdev, 1.0 );
00493         layout.dac_fractional_tolerance = get_tolerance( setup, setup->da_subdev, 1.0 );
00494         /* The bipolar postgain calibration should be good for both
00495          * bipolar and unipolar ranges, so disable separate
00496          * unipolar postgain offset calibration (it will fail
00497          * horribly anyways if you try it).
00498          */
00499         layout.do_adc_unipolar_postgain = 0;
00500         return generic_cal_by_range( setup, &layout );
00501 }
00502 
00503 // converts calibration source voltages from two 16 bit eeprom values to a floating point value
00504 static float eeprom16_to_source( uint16_t *data )
00505 {
00506         union translator
00507         {
00508                 uint32_t bits;
00509                 float   value;
00510         };
00511 
00512         union translator my_translator;
00513 
00514         my_translator.bits = ( data[ 0 ] & 0xffff ) | ( ( data[ 1 ] << 16 ) & 0xffff0000 );
00515 
00516         return my_translator.value;
00517 }
00518 
00519 static float eeprom8_to_source( uint8_t *data )
00520 {
00521         union translator
00522         {
00523                 uint32_t bits;
00524                 float   value;
00525         };
00526         union translator my_translator;
00527         int i;
00528 
00529         my_translator.bits = 0;
00530         for( i = 0; i < 4; i++ )
00531         {
00532                 my_translator.bits |= ( data[ i ] & 0xffff ) << ( 8 * i );
00533         }
00534 
00535         return my_translator.value;
00536 }
00537 
00538 int cb_actual_source_voltage( comedi_t *dev, unsigned int subdevice, unsigned int eeprom_channel, float *voltage)
00539 {
00540         int retval;
00541         unsigned int i;
00542         lsampl_t data;
00543         int max_data;
00544 
00545         max_data = comedi_get_maxdata( dev, subdevice, eeprom_channel );
00546 
00547         if( max_data == 0xffff )
00548         {
00549                 uint16_t word[ 2 ];
00550 
00551                 for( i = 0; i < 2; i++ )
00552                 {
00553                         retval = comedi_data_read( dev, subdevice, eeprom_channel + i, 0, 0, &data );
00554                         if( retval < 0 )
00555                         {
00556                                 comedi_perror( __FUNCTION__ );
00557                                 return retval;
00558                         }
00559                         word[ i ] = data;
00560                 }
00561                 *voltage = eeprom16_to_source( word );
00562         }else if( max_data == 0xff )
00563         {
00564                 uint8_t byte[ 4 ];
00565 
00566                 for( i = 0; i < 4; i++ )
00567                 {
00568                         retval = comedi_data_read( dev, subdevice, eeprom_channel + i, 0, 0, &data );
00569                         if( retval < 0 )
00570                         {
00571                                 comedi_perror( __FUNCTION__ );
00572                                 return retval;
00573                         }
00574                         byte[ i ] = data;
00575                 }
00576                 *voltage = eeprom8_to_source( byte );
00577         }else
00578         {
00579                 fprintf( stderr, "%s: maxdata = 0x%x invalid for subdevice %i, channel %i\n",
00580                         __FUNCTION__, max_data, subdevice, eeprom_channel);
00581                 return -1;
00582         }
00583 
00584         DPRINT(1, "eeprom ch 0x%x gives calibration source of %gV\n", eeprom_channel, *voltage);
00585         return 0;
00586 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines