cio-das800
cio-das801
cio-das802
+cio-das802/16
Options:
[0] - base io address
I've never tested the gain setting stuff since I only have a
DAS-800 board with fixed gain.
+ The cio-das802/16 does not have a fifo-empty status bit! Therefore
+ only fifo-half-full transfers are possible with this card.
+
*/
#include <linux/kernel.h>
#define IRQ 0x8
#define BUSY 0x80
#define DAS800_GAIN 3
+#define FFOV 0x8 // fifo overflow for cio-das802/16
+#define ENHF 0x90 // interrupt fifo half full for cio-das802/16
#define CONTROL1 0x80
#define CONV_CONTROL 0xa0
#define SCAN_LIMITS 0xc0
char *name;
int ai_speed;
comedi_lrange *ai_range;
+ int resolution;
}das800_board;
//analog input ranges
}
};
-enum{das800, ciodas800, das801, ciodas801, das802, ciodas802};
+static comedi_lrange range_das80216_ai = {
+ 8,
+ {
+ RANGE(-10, 10),
+ RANGE(0, 10),
+ RANGE(-5, 5),
+ RANGE(0, 5),
+ RANGE(-2.5, 2.5),
+ RANGE(0, 2.5),
+ RANGE(-1.25, 1.25),
+ RANGE(0, 1.25),
+ }
+};
+
+enum{das800, ciodas800, das801, ciodas801, das802, ciodas802, ciodas80216};
das800_board das800_boards[] =
{
name: "das-800",
ai_speed: 25000,
ai_range: &range_das800_ai,
+ resolution: 12,
},
{
name: "cio-das800",
ai_speed: 20000,
ai_range: &range_das800_ai,
+ resolution: 12,
},
{
name: "das-801",
ai_speed: 25000,
ai_range: &range_das801_ai,
+ resolution: 12,
},
{
name: "cio-das801",
ai_speed: 20000,
ai_range: &range_cio_das801_ai,
+ resolution: 12,
},
{
name: "das-802",
ai_speed: 25000,
ai_range: &range_das802_ai,
+ resolution: 12,
},
{
name: "cio-das802",
ai_speed: 20000,
ai_range: &range_das802_ai,
+ resolution: 12,
+ },
+ {
+ name: "cio-das802/16",
+ ai_speed: 10000,
+ ai_range: &range_das80216_ai,
+ resolution: 16,
},
};
/*
printk(" Board model: CIO-DAS802\n");
return board;
}
+ if(board == ciodas80216)
+ {
+ printk(" Board model: CIO-DAS802/16\n");
+ return board;
+ }
printk(" Board model (probed): DAS-802\n");
return das802;
break;
default :
printk(" Board model: probe returned 0x%x (unknown)\n", id_bits);
- return -1;
+ return board;
break;
}
return -1;
comedi_async *async;
int status;
unsigned long irq_flags;
- static const int max_loops = 256;
+ static const int max_loops = 128; // half-fifo size for cio-das802/16
+ // flags
+ int fifo_empty = 0;
+ int fifo_overflow = 0;
status = inb(dev->iobase + DAS800_STATUS);
- /* if interupt was not generated by board or driver not attached, quit */
+ /* if interrupt was not generated by board or driver not attached, quit */
if(!(status & IRQ) || !(dev->attached))
+ {
return;
+ }
/* wait until here to initialize async, since we will get null dereference
* if interrupt occurs before driver is fully attached!
return;
}
- /* loop while card's fifo is not empty (and make sure loop terminates by limiting to 256 iterations) */
+ if(thisboard->resolution == 16)
+ {
+ fifo_empty = 0; // cio-das802/16 has no fifo-empty status bit
+ fifo_overflow = inb(dev->iobase + DAS800_GAIN) & FFOV;
+ }
+ /* loop while card's fifo is not empty (and limit to half fifo for cio-das802/16) */
for(i = 0; i < max_loops; i++)
{
/* read 16 bits from dev->iobase and dev->iobase + 1 */
dataPoint = inb(dev->iobase + DAS800_LSB);
dataPoint += inb(dev->iobase + DAS800_MSB) << 8;
- if(dataPoint & FIFO_EMPTY) break;
- if( dataPoint & FIFO_OVF )
+ if(thisboard->resolution == 12)
+ {
+ fifo_empty = dataPoint & FIFO_EMPTY;
+ fifo_overflow = dataPoint & FIFO_OVF;
+ }
+ if(fifo_empty)
+ {
+ break;
+ }
+ if(fifo_overflow)
{
comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags);
comedi_error(dev, "DAS800 FIFO overflow");
comedi_error_done(dev, s);
return;
}
- dataPoint = (dataPoint >> 4) & 0xfff; /* strip off extraneous bits */
+ /* strip off extraneous bits for 12 bit cards*/
+ if(thisboard->resolution == 12)
+ dataPoint = (dataPoint >> 4) & 0xfff;
/* if there are more data points to collect */
if(devpriv->count > 0 || devpriv->forever == 1)
{
if(devpriv->count > 0) devpriv->count--;
}
}
- /* we can release spinlock now since we dont case if hardware conversions are enabled anymore */
- comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags);
if(i == max_loops)
comedi_error(dev, "possible problem with loop in interrupt handler");
comedi_bufcheck(dev,s);
if(devpriv->count > 0 || devpriv->forever == 1)
{
- /* Re-enable card's interrupt */
- comedi_spin_lock_irqsave(&dev->spinlock, irq_flags);
+ /* Re-enable card's interrupt.
+ * We already have spinlock, so indirect addressing is safe */
outb(CONTROL1, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be control register 1 */
outb(CONTROL1_INTE | devpriv->do_bits, dev->iobase + DAS800_CONTROL1);
- comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags);
/* otherwise, stop taking data */
} else
{
- /* read 16 bits from dev->iobase and dev->iobase + 1 */
- dataPoint = inb(dev->iobase + DAS800_LSB);
- dataPoint += inb(dev->iobase + DAS800_MSB) << 8;
/* check for overflow on last data point */
- if( dataPoint & FIFO_OVF )
+ if(thisboard->resolution == 12)
+ {
+ fifo_overflow = inb(dev->iobase + DAS800_LSB) & FIFO_OVF;
+ // else cio-das802/16
+ }else
{
+ fifo_overflow = inb(dev->iobase + DAS800_GAIN) & FFOV;
+ }
+ if(fifo_overflow)
+ {
+ comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags);
comedi_error(dev, "DAS800 FIFO overflow");
das800_cancel(dev, dev->subdevices + 0);
comedi_error_done(dev, s);
disable_das800(dev); /* diable hardware triggered conversions */
comedi_done(dev, s);
}
+ comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags);
return;
}
s->subdev_flags = SDF_READABLE;
s->n_chan = 8;
s->len_chanlist = 8;
- s->maxdata = 0xfff;
+ s->maxdata = (1 << thisboard->resolution) - 1;
s->range_table = thisboard->ai_range;
s->do_cmd = das800_ai_do_cmd;
s->do_cmdtest = das800_ai_do_cmdtest;
{
unsigned long irq_flags;
comedi_spin_lock_irqsave(&dev->spinlock, irq_flags);
+ // enable fifo-half full interrupts for
+ if(thisboard->resolution == 16)
+ outb(ENHF, dev->iobase + DAS800_GAIN);
outb(CONV_CONTROL, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be conversion control register */
outb(CONV_HCEN, dev->iobase + DAS800_CONV_CONTROL); /* enable hardware triggering */
outb(CONTROL1, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be control register 1 */
/* set gain */
gain = CR_RANGE(async->cmd.chanlist[0]);
- if( gain > 0)
+ if( thisboard->resolution == 12 && gain > 0)
gain += 0x7;
gain &= 0xf;
outb(gain, dev->iobase + DAS800_GAIN);
/* set gain / range */
range = CR_RANGE(insn->chanspec);
- if(range)
+ if(thisboard->resolution == 12 && range)
range += 0x7;
range &= 0xf;
outb(range, dev->iobase + DAS800_GAIN);