added ni_labpc support
authorFrank Mori Hess <fmhess@speakeasy.net>
Thu, 8 May 2003 23:57:03 +0000 (23:57 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Thu, 8 May 2003 23:57:03 +0000 (23:57 +0000)
comedi_calibrate/Makefile.am
comedi_calibrate/calib.h
comedi_calibrate/comedi_calibrate.c
comedi_calibrate/ni.c
comedi_calibrate/ni_labpc.c [new file with mode: 0644]

index 0acc161606b37e7e0fbeb8d3d3468fac82c697f3..5a3f5e0a8e880bb043acbe894bf27f8c08f163d3 100644 (file)
@@ -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 cal_common.c
+       comedi_calibrate.c ni.c cb.c cb64.c other.c save_cal.c cal_common.c ni_labpc.c
 comedi_calibrate_CFLAGS = $(COMEDILIB_CFLAGS)
 comedi_calibrate_LDADD = $(COMEDILIB_LIBS)
 
index 9c0db22dfb78bda63fc2a5be6c7f05277f82ec53..02ce0a9bf7a8b2995ddffdddd1a78eb8a8d5a7e1 100644 (file)
@@ -37,8 +37,8 @@ typedef struct{
        int maxdata;
        int current;
 
-       int type;
-       double gain;
+//     int type;
+//     double gain;
 }caldac_t;
 
 typedef struct{
@@ -71,9 +71,9 @@ struct calibration_setup_struct {
        int (*do_cal) ( calibration_setup_t *setup );
        char *cal_save_file_path;
        unsigned do_output : 1;
-       void *private_data;
        comedi_calibration_t *old_calibration;
        comedi_calibration_t *new_calibration;
+       void *private_data;
 };
 
 extern int verbose;
@@ -99,10 +99,12 @@ void reset_caldacs( calibration_setup_t *setup);
 extern char ni_id[];
 extern char cb_id[];
 extern char cb64_id[];
+extern char ni_labpc_id[];
 
 int ni_setup( calibration_setup_t*, const char *device_name );
 int cb_setup( calibration_setup_t*, const char *device_name );
 int cb64_setup( calibration_setup_t*, const char *device_name );
+int ni_labpc_setup( calibration_setup_t*, const char *device_name );
 
 /* low level */
 
index 26c6bfff945add3b8ece40fdef525f09ae5dcc58..ea8b9bea0f882bb1211e2a0c434492aeec016a14 100644 (file)
@@ -45,9 +45,6 @@
 /* global variables */
 int verbose = 0;
 
-/* */
-
-
 struct board_struct{
        char *name;
        char *id;
@@ -60,6 +57,7 @@ struct board_struct drivers[] = {
        { "ni_mio_cs",  ni_id,  ni_setup },
        { "cb_pcidas",  cb_id,  cb_setup },
        { "cb_pcidas64",        cb64_id,        cb64_setup },
+       { "ni_labpc", ni_labpc_id,      ni_labpc_setup },
 };
 #define n_drivers (sizeof(drivers)/sizeof(drivers[0]))
 
@@ -234,8 +232,8 @@ ok:
        device_status = setup.status;
 
        if(device_status<STATUS_DONE){
-               printf("Warning: device may not be not fully calibrated due to "
-                       "insufficient information.\n"
+               printf("Warning: device may be incompletely or incorrectly calibrated due to\n"
+                       "insufficient testing.\n"
                        "Please send this output to <ds@schleef.org>.\n"
                        "This output will also allow comedi_calibrate to execute more\n"
                        "quickly in the future.\n");
index 91aef04876667c3f6ecff5bd5447584eb6226a45..15036815ec05802cfdd908530273e77940ec1886 100644 (file)
@@ -1217,8 +1217,9 @@ static double ni_get_reference( calibration_setup_t *setup, int lsb_loc,int msb_
        int16_t uv;
        double ref;
 
-       lsb=read_eeprom( setup, lsb_loc);
-       msb=read_eeprom( setup, msb_loc);
+       lsb=read_eeprom( setup, lsb_loc );
+       msb=read_eeprom( setup, msb_loc );
+       assert( lsb >=0 && msb >= 0 );
        DPRINT(0,"eeprom reference lsb=%d msb=%d\n", lsb, msb);
 
        uv = ( lsb & 0xff ) | ( ( msb << 8 ) & 0xff00 );
diff --git a/comedi_calibrate/ni_labpc.c b/comedi_calibrate/ni_labpc.c
new file mode 100644 (file)
index 0000000..15adfb4
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+   calibration support for NI labpc and compatible boards
+
+   copyright (C) 2003 by Frank Mori Hess
+
+ */
+
+/***************************************************************************
+ *                                                                         *
+ *   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.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <getopt.h>
+#include <ctype.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "calib.h"
+
+char ni_labpc_id[] = "$Id$";
+
+int ni_labpc_setup( calibration_setup_t *setup , const char *device_name );
+static int cal_ni_labpc( calibration_setup_t *setup );
+
+enum labpc_caldacs
+{
+       DAC0_GAIN = 1,
+       ADC_OFFSET_FINE = 2,
+       DAC1_GAIN = 5,
+       ADC_GAIN = 6,
+       ADC_OFFSET_COARSE_ALT = 7,
+       DAC1_OFFSET = 9,
+       ADC_POSTGAIN_OFFSET = 10,
+       DAC0_OFFSET_ALT = 11,
+       ADC_OFFSET_COARSE = 12,
+       DAC0_OFFSET = 13,
+};
+static inline unsigned int DAC_OFFSET( unsigned int channel )
+{
+       if( channel ) return DAC1_OFFSET;
+       else return DAC0_OFFSET;
+}
+static inline unsigned int DAC_GAIN( unsigned int channel )
+{
+       if( channel ) return DAC1_GAIN;
+       else return DAC0_GAIN;
+}
+
+int ni_labpc_setup( calibration_setup_t *setup , const char *device_name )
+{
+       if( setup->caldac_subdev < 0 )
+       {
+               fprintf( stderr, "no caldac subdevice found\n");
+               return -1;
+       }
+       setup->status = STATUS_DONE;
+       setup->do_cal = cal_ni_labpc;
+       setup_caldacs( setup, setup->caldac_subdev );
+
+       return 0;
+}
+
+
+/* load analog input caldacs from eeprom values (depend on range used) */
+static void labpc_grab_ai_calibration( calibration_setup_t *setup, unsigned int range )
+{
+       comedi_calibration_setting_t *current_cal;
+       /* points to (end of) analog input bipolar calibration values */
+       const int ai_bip_frame = read_eeprom( setup, 127 );
+       enum offset_indices
+       {
+               coarse_offset_index = 0,
+               fine_offset_index = -1,
+       };
+       /* points to (end of) analog input unipolar calibration values */
+       const int ai_unip_frame = read_eeprom( setup, 126 );
+       /* points to (end of) analog input bipolar calibration values */
+       const int bip_gain_frame = read_eeprom( setup, 123 );
+       /* points to (end of) analog input bipolar calibration values */
+       const int unip_gain_frame = read_eeprom( setup, 122 );
+       /* points to (end of) analog input bipolar calibration values */
+       const int bip_offset_frame = read_eeprom( setup, 121 );
+       /* points to (end of) analog input bipolar calibration values */
+       const int unip_offset_frame = read_eeprom( setup, 120 );
+       int ai_frame, gain_frame, offset_frame;
+       /* eeprom offsets by range */
+       int range_to_index[ 14 ] =
+       {
+               0,
+               -2,
+               -3,
+               -4,
+               -5,
+               -6,
+               -7,
+               0,
+               -2,
+               -3,
+               -4,
+               -5,
+               -6,
+               -7,
+       };
+       int value;
+
+       if( is_unipolar( setup->dev, setup->ad_subdev, 0, range ) )
+       {
+               ai_frame = ai_unip_frame;
+               gain_frame = unip_gain_frame;
+               offset_frame = unip_offset_frame;
+       }else
+       {
+               ai_frame = ai_bip_frame;
+               gain_frame = bip_gain_frame;
+               offset_frame = bip_offset_frame;
+       }
+       assert( ai_frame >=0 && gain_frame >= 0 && offset_frame >= 0 );
+
+       current_cal = sc_alloc_calibration_setting( setup );
+
+       /* load coarse offset */
+       value = read_eeprom( setup, ai_frame + coarse_offset_index );
+       assert( value >= 0 );
+       update_caldac( setup, ADC_OFFSET_COARSE, value );
+       sc_push_caldac( current_cal, setup->caldacs[ ADC_OFFSET_COARSE ] );
+       update_caldac( setup, ADC_OFFSET_COARSE_ALT, value );
+       sc_push_caldac( current_cal, setup->caldacs[ ADC_OFFSET_COARSE_ALT ] );
+
+       /* load fine offset */
+       value = read_eeprom( setup, ai_frame + fine_offset_index );
+       assert( value >= 0 );
+       update_caldac( setup, ADC_OFFSET_FINE, value );
+       sc_push_caldac( current_cal, setup->caldacs[ ADC_OFFSET_FINE ] );
+
+       /* load postgain offset */
+       value = read_eeprom( setup, offset_frame + range_to_index[ range ] );
+       assert( value >= 0 );
+       update_caldac( setup, ADC_POSTGAIN_OFFSET, value );
+       sc_push_caldac( current_cal, setup->caldacs[ ADC_POSTGAIN_OFFSET ] );
+
+       /* load gain */
+       value = read_eeprom( setup, gain_frame + range_to_index[ range ] );
+       assert( value >= 0 );
+       update_caldac( setup, ADC_GAIN, value );
+       sc_push_caldac( current_cal, setup->caldacs[ ADC_GAIN ] );
+
+       current_cal->subdevice = setup->ad_subdev;
+       sc_push_channel( current_cal, SC_ALL_CHANNELS );
+       sc_push_range( current_cal, range );
+       sc_push_aref( current_cal, SC_ALL_AREFS );
+}
+
+static int ao_offset_index( unsigned int channel )
+{
+       if( channel ) return -2;
+       else return 0;
+}
+
+static int ao_gain_index( unsigned int channel )
+{
+       if( channel ) return -3;
+       else return -1;
+}
+
+/* load analog output caldacs from eeprom values (depend on range used) */
+static void labpc_grab_ao_calibration( calibration_setup_t *setup,
+       unsigned int channel, unsigned int range)
+{
+       comedi_calibration_setting_t *current_cal;
+       /* points to (end of) analog output bipolar calibration values */
+       int ao_bip_frame = read_eeprom( setup, 125 );
+       /* points to (end of) analog output bipolar calibration values */
+       int ao_unip_frame = read_eeprom( setup, 124 );
+       int ao_frame;
+       int value;
+
+       current_cal = sc_alloc_calibration_setting( setup );
+
+       if( is_unipolar( setup->dev, setup->da_subdev, 0, range ) )
+               ao_frame = ao_unip_frame;
+       else
+               ao_frame = ao_bip_frame;
+       assert( ao_frame >= 0 );
+
+       /* load offset */
+       value = read_eeprom( setup, ao_frame + ao_offset_index( channel ) );
+       assert( value >= 0 );
+       update_caldac( setup, DAC_OFFSET( channel ), value );
+       sc_push_caldac( current_cal, setup->caldacs[ DAC_OFFSET( channel ) ] );
+       if( channel == 0 )
+       {
+               update_caldac( setup, DAC0_OFFSET_ALT, value );
+               sc_push_caldac( current_cal, setup->caldacs[ DAC0_OFFSET_ALT ] );
+       }
+
+       // load gain calibration
+       value = read_eeprom( setup, ao_frame + ao_gain_index( channel ) );
+       assert( value >= 0 );
+       update_caldac( setup, DAC_GAIN( channel ), value );
+       sc_push_caldac( current_cal, setup->caldacs[ DAC_GAIN( channel ) ] );
+
+       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 cal_ni_labpc( calibration_setup_t *setup )
+{
+       int range, channel, num_ai_ranges, num_ao_ranges;
+
+       if( comedi_get_version_code( setup->dev ) <= COMEDI_VERSION_CODE( 0, 7, 66 ) )
+       {
+               DPRINT(0, "WARNING: you need comedi driver version 0.7.67 or later\n"
+                "for this calibration to work properly\n" );
+       }
+
+       num_ai_ranges = comedi_get_n_ranges( setup->dev, setup->ad_subdev, 0 );
+       assert( num_ai_ranges > 0 );
+       num_ao_ranges = comedi_get_n_ranges( setup->dev, setup->da_subdev, 0 );
+       assert( num_ao_ranges > 0 );
+
+       for( range = 0; range < num_ai_ranges; range++ )
+               labpc_grab_ai_calibration( setup, range );
+
+       if( setup->da_subdev >= 0 && setup->do_output )
+       {
+               for( channel = 0; channel < 2; channel++ )
+               {
+                       for( range = 0; range < num_ao_ranges; range++ )
+                               labpc_grab_ao_calibration( setup, channel, range );
+               }
+       }
+
+       return write_calibration_file( setup );
+}
+