added checking for valid aref. 611x calibration support.
authorFrank Mori Hess <fmhess@speakeasy.net>
Mon, 18 Nov 2002 17:03:06 +0000 (17:03 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Mon, 18 Nov 2002 17:03:06 +0000 (17:03 +0000)
Contributors
comedi/drivers/ni_mio_common.c
comedi/drivers/ni_stc.h
comedi/range.c

index 30509962c10c8f99f6b37e1ea0fa1ae2fff9affa..7a5f0ad9947fa2a14a8f324ed0c9701a92191549 100644 (file)
@@ -22,3 +22,7 @@ Tim Ousley <tim.ousley@ni.com>
 Dan Christian <dac@ptolemy.arc.nasa.gov>
 Ivan Martinez <ivanmr@altavista.com>
 Emmanuel PACAUD <emmanuel.pacaud@univ-poitiers.fr>
+John Hallen
+Rolf Mueller
+Herbert Peremans
+Herman Bruyninckx
index 4da44ebe35691f9f9696af4a64b95e2d884c162f..ad9b0ac46f2788901cd5b4aaebdc49f3ec80171b 100644 (file)
 
 #define NI_TIMEOUT 1000
 
-/* reference: ground, common, differential, other */
-static short ni_modebits1[4]={ 0x3000, 0x2000, 0x1000, 0 };
-static short ni_modebits2[4]={ 0x3f, 0x3f, 0x37, 0x37 };
-
 /* Note: this table must match the ai_gain_* definitions */
 static short ni_gainlkup[][16]={
        /* ai_gain_16 */
@@ -1247,28 +1243,42 @@ static void ni_load_channelgain_list(comedi_device *dev,unsigned int n_chan,
        offset=1<<(boardtype.adbits-1);
        for(i=0;i<n_chan;i++){
                if(list[i]&CR_ALT_SOURCE){
-                       chan=CR_CHAN(devpriv->ai_calib_chanspec);
-                       range=CR_RANGE(devpriv->ai_calib_chanspec);
-                       aref=AREF_OTHER;
-                       dither=((devpriv->ai_calib_chanspec&CR_ALT_FILTER)!=0);
+                       chan=devpriv->ai_calib_source;
                }else{
                        chan=CR_CHAN(list[i]);
-                       range=CR_RANGE(list[i]);
-                       aref=CR_AREF(list[i]);
-                       dither=((list[i]&CR_ALT_FILTER)!=0);
                }
+               aref=CR_AREF(list[i]);
+               range=CR_RANGE(list[i]);
+               dither=((list[i]&CR_ALT_FILTER)!=0);
 
                /* fix the external/internal range differences */
                range = ni_gainlkup[boardtype.gainlkup][range];
                devpriv->ai_xorlist[i] = (range&0x100)?0:offset;
 
-               if(boardtype.gainlkup != ai_gain_611x){
-                       hi=ni_modebits1[aref]|(chan&ni_modebits2[aref]);
-               }else{
-                       /* map everything to differential */
-                       hi = AI_DIFFERENTIAL;
-                       hi |= AI_CONFIG_CHANNEL( chan );
+               hi = 0;
+               if( ( list[i] & CR_ALT_SOURCE ) )
+               {
+                       if( boardtype.reg_611x )
+                               ni_writew(CR_CHAN(list[i])&0x0003, Calibration_Channel_Select_611x);
+               }else
+               {
+                       switch( aref )
+                       {
+                               case AREF_DIFF:
+                                       hi |= AI_DIFFERENTIAL;
+                                       break;
+                               case AREF_COMMON:
+                                       hi |= AI_COMMON;
+                                       break;
+                               case AREF_GROUND:
+                                       hi |= AI_GROUND;
+                                       break;
+                               case AREF_OTHER:
+                                       break;
+                       }
                }
+               hi |= AI_CONFIG_CHANNEL( chan );
+
                ni_writew(hi,Configuration_Memory_High);
 
                lo = range;
@@ -1796,10 +1806,9 @@ static int ni_ai_insn_config(comedi_device *dev,comedi_subdevice *s,
                break;
        case INSN_CONFIG_ALT_SOURCE:
                {
-               if(CR_CHAN(data[1]) >= 8 ||
-                  CR_RANGE(data[1]) >= s->range_table->length)
+               if(data[1] >= 8)
                        return -EINVAL;
-               devpriv->ai_calib_chanspec = data[1];
+               devpriv->ai_calib_source = data[1];
                return 2;
                }
        }
@@ -2369,8 +2378,8 @@ static int ni_E_init(comedi_device *dev,comedi_devconfig *it)
        if(boardtype.n_adchan){
                s->type=COMEDI_SUBD_AI;
                s->subdev_flags=SDF_READABLE|SDF_DIFF;
-               if( boardtype.reg_611x == 0 )   // driver doesn't seem to support ground/common for any boards?
-                       s->subdev_flags |= SDF_GROUND | SDF_COMMON;
+               if( boardtype.reg_611x == 0 )
+                       s->subdev_flags |= SDF_GROUND | SDF_COMMON | SDF_OTHER;
 
                s->subdev_flags|=SDF_DITHER;
                s->n_chan=boardtype.n_adchan;
@@ -2673,7 +2682,7 @@ static void ni_write_caldac(comedi_device *dev,int addr,int val)
        unsigned int loadbit=0,bits=0,bit,bitstring=0;
        int i;
        int type;
-       
+
        //printk("ni_write_caldac: chan=%d val=%d\n",addr,val);
 
        for(i=0;i<3;i++){
@@ -3201,7 +3210,7 @@ static void GPCT_Reset(comedi_device *dev, int chan)
        
        win_out( devpriv->gpct_mode[chan],G_Mode_Register(chan));
        win_out( devpriv->gpct_input_select[chan],G_Input_Select_Register(chan));
-       win_out( 0,G_Autoincrement_Register(chan)); 
+       win_out( 0,G_Autoincrement_Register(chan));
                
        //printk("exit GPCT_Reset\n");
 }
@@ -3289,7 +3298,7 @@ static int ni_gpct_insn_read(comedi_device *dev,comedi_subdevice *s,
 
        int chan=insn->chanspec;
        int cur_op = devpriv->gpct_cur_operation[chan];
-               
+
        //printk("in ni_gpct_insn_read, n=%d, data[0]=%d\n",insn->chanspec,data[0]);
        if(insn->n!=1)return -EINVAL;
                
index 09c00551dfaf7ae2c03e5a6c16f384d38178c069..739765c19dbb5d103aff7379705f4f27e08666f2 100644 (file)
@@ -612,10 +612,12 @@ enum Configuration_Memory_High_Bits
 {
        AI_AC_COUPLE    = 0x800,
        AI_DIFFERENTIAL = 0x1000,
+       AI_COMMON = 0x2000,
+       AI_GROUND = 0x3000,
 };
 static inline unsigned int AI_CONFIG_CHANNEL( unsigned int channel )
 {
-       return ( channel & 0x7 );
+       return ( channel & 0x3f );
 }
 
 #define ADC_FIFO_Data_Register         0x1c
@@ -733,7 +735,7 @@ static ni_board ni_boards[];
        int ai_continuous;                                      \
        int blocksize;                                          \
        int n_left;                                             \
-       unsigned int ai_calib_chanspec;                         \
+       unsigned int ai_calib_source;                           \
                                                                \
        int changain_state;                                     \
        unsigned int changain_spec;                             \
index 7de6d663a7ed1b3654d9832dca3ada8d90fceb17..7aa7d7b45ec6f76b55c7d4d7475e19f7441bc3ae 100644 (file)
@@ -87,6 +87,31 @@ int do_rangeinfo_ioctl(comedi_device *dev,comedi_rangeinfo *arg)
        return 0;
 }
 
+static int aref_invalid( comedi_subdevice *s, unsigned int chanspec )
+{
+       unsigned int aref;
+
+       aref = CR_AREF( chanspec );
+       switch( aref )
+       {
+               case AREF_DIFF:
+                       if( s->subdev_flags & SDF_DIFF ) return 0;
+                       break;
+               case AREF_COMMON:
+                       if( s->subdev_flags & SDF_COMMON ) return 0;
+                       break;
+               case AREF_GROUND:
+                       if( s->subdev_flags & SDF_GROUND ) return 0;
+                       break;
+               case AREF_OTHER:
+                       if( s->subdev_flags & SDF_OTHER ) return 0;
+                       break;
+               default:
+                       break;
+       }
+       DPRINTK("subdevice does not support aref %i", aref);
+       return 1;
+}
 
 /*
    This function checks each element in a channel/gain list to make
@@ -100,8 +125,9 @@ int check_chanlist(comedi_subdevice *s,int n,unsigned int *chanlist)
 
        if(s->range_table){
                for(i=0;i<n;i++)
-                       if(CR_CHAN(chanlist[i])>=s->n_chan || 
-                          CR_RANGE(chanlist[i])>=s->range_table->length){
+                       if(CR_CHAN(chanlist[i])>=s->n_chan ||
+                               CR_RANGE(chanlist[i])>=s->range_table->length ||
+                               aref_invalid( s, chanlist[i] ) ){
                                rt_printk("bad chanlist[%d]=0x%08x n_chan=%d range length=%d\n",
                                        i,chanlist[i],s->n_chan,s->range_table->length);
 #if 0
@@ -115,7 +141,8 @@ for(i=0;i<n;i++){
                for(i=0;i<n;i++){
                        chan=CR_CHAN(chanlist[i]);
                        if(chan>=s->n_chan ||
-                          CR_RANGE(chanlist[i])>=s->range_table_list[chan]->length){
+                               CR_RANGE(chanlist[i])>=s->range_table_list[chan]->length ||
+                               aref_invalid( s, chanlist[i] ) ){
                                rt_printk("bad chanlist[%d]=0x%08x\n",i,chanlist[i]);
                                return -EINVAL;
                        }