{
daqboard2000_hw *fpga = devpriv->daq;
- comedi_udelay(4);
+// comedi_udelay(4);
fpga->acqScanListFIFO = entry & 0x00ff;
- comedi_udelay(4);
+// comedi_udelay(4);
fpga->acqScanListFIFO = (entry >> 8) & 0x00ff;
}
daqboard2000_hw *fpga = devpriv->daq;
int gain, chan, timeout;
- /* Could these two be merged? */
- fpga->acqControl = DAQBOARD2000_AcqResetScanListFifo;
- fpga->acqControl = DAQBOARD2000_AcqResetResultsFifo | DAQBOARD2000_AcqResetConfigPipe;
+ fpga->acqControl =
+ DAQBOARD2000_AcqResetScanListFifo |
+ DAQBOARD2000_AcqResetResultsFifo |
+ DAQBOARD2000_AcqResetConfigPipe;
+
+ /* If pacer clock is not set to some high value (> 10 us), we
+ risk multiple samples to be put into the result FIFO. */
+ fpga->acqPacerClockDivLow = 1000000; /* 1 second, should be long enough */
+ fpga->acqPacerClockDivHigh = 0;
gain = CR_RANGE(insn->chanspec);
chan = CR_CHAN(insn->chanspec);
{
int result = 0;
if(dir){
- writew(data, (void*)(ioaddr+port*2));
+ writew(data,ioaddr+port*2);
result = 0;
}else{
- result = readw((void*)(ioaddr+port*2));
+ result = readw(ioaddr+port*2);
}
/*
printk("daqboard2000_8255_cb %x %d %d %2.2x -> %2.2x\n",
{
int i,n;
int chan;
- unsigned short hi, lo;
- int16_t raw_data;
+ unsigned int hi, lo;
chan = CR_CHAN(insn->chanspec);
outw(MULTIQ3_CONTROL_MUST | MULTIQ3_AD_MUX_EN | (chan<<3),
hi = inb(dev->iobase + MULTIQ3_AD_CS);
lo = inb(dev->iobase + MULTIQ3_AD_CS);
- raw_data = ((hi << 8) & 0xff00) | (lo & 0xff);
- raw_data += 0x1000;
- data[n] = raw_data & 0x1fff;
+ data[n] = (((hi << 8) | lo) + 0x1000) & 0x1fff;
}
return n;
int control = MULTIQ3_CONTROL_MUST | MULTIQ3_AD_MUX_EN | (chan<<3);
for(n=0;n<insn->n;n++){
+ int value;
outw(control, dev->iobase+MULTIQ3_CONTROL);
outb(MULTIQ3_BP_RESET, dev->iobase+MULTIQ3_ENC_CONTROL);
outb(MULTIQ3_TRSFRCNTR_OL, dev->iobase+MULTIQ3_ENC_CONTROL);
- data[n] = inb(dev->iobase+MULTIQ3_ENC_DATA);
- data[n] |= (inb(dev->iobase+MULTIQ3_ENC_DATA)<<8);
- data[n] |= (inb(dev->iobase+MULTIQ3_ENC_DATA)<<16);
+ value = inb(dev->iobase+MULTIQ3_ENC_DATA);
+ value |= (inb(dev->iobase+MULTIQ3_ENC_DATA)<<8);
+ value |= (inb(dev->iobase+MULTIQ3_ENC_DATA)<<16);
+ data[n] = (value + 0x800000) & 0xffffff;
}
return n;
#include <linux/delay.h>
#include <linux/ioport.h>
+#include <termios.h>
+#include <asm/ioctls.h>
+#include <linux/serial.h>
+#include <linux/poll.h>
/*
* Board descriptions for two imaginary boards. Describing the
unsigned char digital_out_mapping[32];
unsigned char analog_in_mapping[32];
unsigned char analog_out_mapping[32];
+ unsigned char encoder_in_mapping[32];
serial2002_range_table_t in_range[32], out_range[32];
} serial2002_private;
+
/*
* most drivers define the following macro to make it easy to
* access the private structure.
static int tty_read(struct file *f, int timeout)
{
- int result, retries;
- mm_segment_t oldfs;
+ int result;
result = -1;
if (!IS_ERR(f)) {
- retries = 0;
+ mm_segment_t oldfs;
+
oldfs = get_fs();
set_fs(KERNEL_DS);
- while (retries < timeout) {
+ if (f->f_op->poll) {
+ struct poll_wqueues table;
+ struct timeval start, now;
+
+ do_gettimeofday(&start);
+ poll_initwait(&table);
+ while (1) {
+ long elapsed;
+ int mask;
+
+ mask = f->f_op->poll(f, &table);
+ if (mask & (POLLRDNORM|POLLRDBAND|POLLIN|POLLHUP|POLLERR)) { break; }
+ do_gettimeofday(&now);
+ elapsed = (1000000 * (now.tv_sec - start.tv_sec) +
+ now.tv_usec - start.tv_usec);
+ if (elapsed > timeout) { break; }
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(((timeout - elapsed)* HZ) / 10000);
+ }
+ poll_freewait(&table);
+ } else {
+ /* Device does not support poll, busy wait */
+ int retries = 0;
+ while (1) {
retries++;
+ if (retries >= timeout) { break; }
+ if (tty_available(f) > 0) { break; }
+ comedi_udelay(100);
+ }
+ }
if (tty_available(f) > 0) {
- int count;
unsigned char ch;
f->f_pos = 0;
- count = f->f_op->read(f, &ch, 1, &f->f_pos);
- if (count == 1) { result = ch; }
- break;
+ if (f->f_op->read(f, &ch, 1, &f->f_pos) == 1) {
+ result = ch;
}
- comedi_udelay(100);
}
set_fs(oldfs);
}
{
// Set low latency
struct serial_struct settings;
- int i;
f->f_op->ioctl(f->f_dentry->d_inode, f, TIOCGSERIAL, (int)&settings);
settings.flags |= ASYNC_LOW_LATENCY;
f->f_op->ioctl(f->f_dentry->d_inode, f, TIOCSSERIAL, (int)&settings);
length++;
if (data < 0) {
+ printk("serial2002 error\n");
break;
} else if (data & 0x80) {
result.value = (result.value << 7) | (data & 0x7f);
}
}
-static int serial_2002_open(comedi_device *dev) {
+static void serial_2002_open(comedi_device *dev) {
char port[20];
sprintf(port, "/dev/ttyS%d", devpriv->port);
}
}
}
- for (i = 0 ; i < 4 ; i++) {
+ for (i = 0 ; i <= 4 ; i++) {
// Fill in subdev data
config_t *c;
unsigned char *mapping = 0;
} break;
case 4: {
c = chan_in_config;
- c = 0; // Counters/encoder not implemented yet
+ mapping = devpriv->encoder_in_mapping;
+ range = devpriv->in_range;
kind = 5;
} break;
default: { c = 0; } break;
range[j].range.max = c[j].max;
s->range_table_list[chan] = (comedi_lrange*)&range[j];
}
- s->maxdata_list[chan] = (1<<c[j].bits) - 1;
+ s->maxdata_list[chan] = ((long long)1<<c[j].bits) - 1;
chan++;
}
}
}
}
}
- return 0;
}
-static int serial_2002_close(comedi_device *dev) {
+static void serial_2002_close(comedi_device *dev) {
if (!IS_ERR(devpriv->tty) && (devpriv->tty != 0)) {
filp_close(devpriv->tty, 0);
}
- return 0;
}
static int serial2002_di_rinsn(comedi_device *dev, comedi_subdevice *s,
return n;
}
-static int serial2002_attach(comedi_device *dev,comedi_devconfig *it)
+static int serial2002_ei_rinsn(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ int n;
+ int chan;
+
+ chan = devpriv->encoder_in_mapping[CR_CHAN(insn->chanspec)];
+ for(n = 0 ; n < insn->n ; n++){
+ struct serial_data read;
+
+ poll_channel(devpriv->tty, chan);
+ while (1) {
+ read = serial_read(devpriv->tty, 1000);
+ if (read.kind != is_channel || read.index == chan) { break; }
+ }
+ data[n] = read.value;
+ }
+ return n;
+}
+
+static int serial2002_attach(comedi_device *dev, comedi_devconfig *it)
{
comedi_subdevice *s;
devpriv->speed = it->options[1];
printk("/dev/ttyS%d @ %d\n", devpriv->port, devpriv->speed);
- if(alloc_subdevices(dev, 4)<0)
+ if(alloc_subdevices(dev, 5)<0)
return -ENOMEM;
/* digital input subdevice */
s->insn_write = &serial2002_ao_winsn;
s->insn_read = &serial2002_ao_rinsn;
+ /* encoder input subdevice */
+ s=dev->subdevices+4;
+ s->type = COMEDI_SUBD_COUNTER;
+ s->subdev_flags = SDF_READABLE | SDF_LSAMPL;
+ s->n_chan = 0;
+ s->maxdata = 1;
+ s->range_table = 0;
+ s->insn_read = &serial2002_ei_rinsn;
+
printk("attached\n");
return 1;