Fixed bugs reported by csp@andrew.cmu.edu. The bug report was as follows:
authorFrank Mori Hess <fmhess@speakeasy.net>
Wed, 29 Dec 2004 01:07:18 +0000 (01:07 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Wed, 29 Dec 2004 01:07:18 +0000 (01:07 +0000)
I have been attempting to get a NI-ATAO10, a 10 channel legacy ISA analog output
board, working with comedi. Apparantely the way comedi_from_phys works to
convert voltage to sample doesn't seem to work correctly with the ATAO10 board.
I found that the correct sample data for the ATAO10 board is as follows:

In unipolar mode
0V = 2048
+10V = 6143

In bipolar mode
-10V = 2048
+10V = 6143

It seems that comedi_from_phys is somehow shifted by 2048 from what it should be
(comedi_from_phys gives values from 0 to 4095).

Furthermore, comedi does not detect the polarity of the board (I'm not sure if
this is possible on this board); thus the range is always reported as -10V to
+10V even if the board is set on unipolar mode (which is achieved by setting
jumpers on the board).

Finally, for some reason, channel 0 does not work with Comedi (the board fully
works in Windows). The other 9 channels work.

comedi/drivers/ni_at_ao.c

index c8656f4e8c84f62538221141238ba5dbfa5d5ec4..546013ea56de77f7ad0a0e3d76176ed5821e323c 100644 (file)
 Driver: ni_at_ao.o
 Description: National Instruments AT-AO-6/10
 Devices: [National Instruments] AT-AO-6 (at-ao-6), AT-AO-10 (at-ao-10)
-Status: untested
+Status: should work
 Author: ds
-Updated: Fri,  7 Jun 2002 13:20:30 -0700
+Updated: Sun Dec 26 12:26:28 EST 2004
 
-This driver has not been tested, but should work.
+Configuration options:
+  [0] - I/O port base address
+  [1] - IRQ (unused)
+  [2] - DMA (unused)
+  [3] - analog output range, set by jumpers on hardware (0 for -10 to 10V bipolar, 1 for 0V to 10V unipolar)
 
 */
 /*
@@ -204,10 +208,12 @@ static int atao_attach(comedi_device *dev,comedi_devconfig *it)
 {
        comedi_subdevice *s;
        unsigned long iobase;
-
+       int ao_unipolar;
+       
        iobase = it->options[0];
        if(iobase==0)iobase = 0x1c0;
-
+       ao_unipolar = it->options[3];
+       
        printk("comedi%d: ni_at_ao: 0x%04lx",dev->minor,iobase);
        
        if(check_region(iobase, ATAO_SIZE) < 0){
@@ -233,7 +239,10 @@ static int atao_attach(comedi_device *dev,comedi_devconfig *it)
        s->subdev_flags=SDF_WRITABLE;
        s->n_chan=thisboard->n_ao_chans;
        s->maxdata=(1<<12)-1;
-       s->range_table=&range_bipolar10;
+       if(ao_unipolar)
+               s->range_table=&range_unipolar10;
+       else
+               s->range_table=&range_bipolar10;
        s->insn_write = &atao_ao_winsn;
        s->insn_read = &atao_ao_rinsn;
 
@@ -299,14 +308,14 @@ static void atao_reset(comedi_device *dev)
        
        inw(dev->iobase + ATAO_FIFO_CLEAR);
 
-       devpriv->cfg1 = GRP2WR;
+       devpriv->cfg1 |= GRP2WR;
        outw(devpriv->cfg1, dev->iobase + ATAO_CFG1);
 
        outw(0, dev->iobase + ATAO_2_INT1CLR);
        outw(0, dev->iobase + ATAO_2_INT2CLR);
        outw(0, dev->iobase + ATAO_2_DMATCCLR);
 
-       devpriv->cfg1 = 0;
+       devpriv->cfg1 &= ~GRP2WR;
        outw(devpriv->cfg1, dev->iobase + ATAO_CFG1);
 }
 
@@ -315,9 +324,21 @@ static int atao_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *ins
 {
        int i;
        int chan = CR_CHAN(insn->chanspec);
-
+       short bits;
+       
        for(i=0;i<insn->n;i++){
-               outw(data[i], dev->iobase + ATAO_DACn(chan));
+               bits = data[i] - 0x800;
+               if(chan == 0)
+               {
+                       devpriv->cfg1 |= GRP2WR;
+                       outw(devpriv->cfg1, dev->iobase + ATAO_CFG1);
+               }
+               outw(bits, dev->iobase + ATAO_DACn(chan));
+               if(chan == 0)
+               {
+                       devpriv->cfg1 &= ~GRP2WR;
+                       outw(devpriv->cfg1, dev->iobase + ATAO_CFG1);
+               }
                devpriv->ao_readback[chan] = data[i];
        }