comedilib/lib/sv.c
2000-02-02 05:14:23 +00:00

188 lines
3.4 KiB
C

/*
lib/sv.c
comedi library routines - sv section
COMEDI - Linux Control and Measurement Device Interface
Copyright (C) 1997-8 David A. Schleef <ds@stm.lbl.gov>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <comedi.h>
#include <string.h>
#include <libinternal.h>
int sv_measure_l(comedi_sv_t *it,double *data);
int sv_measure_s(comedi_sv_t *it,double *data);
int comedi_sv_init(comedi_sv_t *it,comedi_t *dev,unsigned int subd,unsigned int chan)
{
if(!valid_chan(dev,subd,chan))return -1;
if(!it)return -1;
memset(it,0,sizeof(*it));
it->dev=dev;
it->subdevice=subd;
it->chan=chan;
it->n=100;
return comedi_sv_update(it);
}
int comedi_sv_update(comedi_sv_t *it)
{
if(!it)return -1;
if(!valid_chan(it->dev,it->subdevice,it->chan))return -1;
it->maxdata=comedi_get_maxdata(it->dev,it->subdevice,it->chan);
/* check current range policy */
/* check n */
return 0;
}
int comedi_sv_measure(comedi_sv_t *it,double *data)
{
if(it->dev->subdevices[it->subdevice].subd_flags & SDF_LSAMPL){
return sv_measure_l(it,data);
}else{
return sv_measure_s(it,data);
}
}
int sv_measure_l(comedi_sv_t *it,double *data)
{
comedi_trig t;
int ret=0;
lsampl_t *val;
unsigned int chan;
comedi_range *rng;
double sum;
int i;
int n;
val=malloc(sizeof(*val)*it->n);
chan=CR_PACK(it->chan,it->range,it->aref);
t.subdev=it->subdevice;
t.mode=0;
t.flags=TRIG_DITHER;
t.n_chan=1;
t.chanlist=&chan;
t.trigsrc=0;
t.trigvar=0;
t.trigvar1=0;
rng=comedi_get_range(it->dev,it->subdevice,it->chan,it->range);
for(n=0;n<it->n;){
t.data=(void *)(val+n);
t.n=it->n-n;
i=ioctl_trigger(it->dev->fd,&t);
if(i<=0){
ret=i;
goto out;
}
n+=i;
}
sum=0;
for(i=0;i<it->n;i++){
sum+=comedi_to_phys(val[i],rng,it->maxdata);
}
*data=sum/it->n;
out:
free(val);
return ret;
}
/* yes, these functions are _almost_ exactly the same... */
int sv_measure_s(comedi_sv_t *it,double *data)
{
comedi_trig t;
int ret=0;
sampl_t *val;
unsigned int chan;
comedi_range *rng;
double sum;
int i;
int n;
val=malloc(sizeof(*val)*it->n);
chan=CR_PACK(it->chan,it->range,it->aref);
t.subdev=it->subdevice;
t.mode=0;
t.flags=TRIG_DITHER;
t.n_chan=1;
t.chanlist=&chan;
t.data=val;
t.n=it->n;
t.trigsrc=0;
t.trigvar=0;
t.trigvar1=0;
rng=comedi_get_range(it->dev,it->subdevice,it->chan,it->range);
for(n=0;n<it->n;){
t.data=val+n;
t.n=it->n-n;
i=ioctl_trigger(it->dev->fd,&t);
if(i<=0){
ret=i;
goto out;
}
n+=i;
}
sum=0;
for(i=0;i<it->n;i++){
sum+=comedi_to_phys(val[i],rng,it->maxdata);
}
*data=sum/it->n;
out:
free(val);
return ret;
}