from ds
[comedilib.git] / lib / sv.c
1 /*
2     lib/sv.c
3     functions for slowly varying inputs
4
5     COMEDILIB - Linux Control and Measurement Device Interface Library
6     Copyright (C) 1997-2001 David A. Schleef <ds@schleef.org>
7
8     This library is free software; you can redistribute it and/or
9     modify it under the terms of the GNU Lesser General Public
10     License as published by the Free Software Foundation, version 2.1
11     of the License.
12
13     This library is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16     Lesser General Public License for more details.
17
18     You should have received a copy of the GNU Lesser General Public
19     License along with this library; if not, write to the Free Software
20     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
21     USA.
22 */
23
24 #include <stdio.h>
25 #include <math.h>
26 #include <stdlib.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <sys/ioctl.h>
32 #include <errno.h>
33 #include <comedi.h>
34 #include <string.h>
35
36 #include <libinternal.h>
37
38
39
40 int sv_measure_l(comedi_sv_t *it,double *data);
41 int sv_measure_s(comedi_sv_t *it,double *data);
42
43
44 int comedi_sv_init(comedi_sv_t *it,comedi_t *dev,unsigned int subd,unsigned int chan)
45 {
46         if(!valid_chan(dev,subd,chan))return -1;
47         if(!it)return -1;
48
49         memset(it,0,sizeof(*it));
50
51         it->dev=dev;
52         it->subdevice=subd;
53         it->chan=chan;
54         it->n=100;
55
56         return comedi_sv_update(it);
57 }
58
59 int comedi_sv_update(comedi_sv_t *it)
60 {
61         if(!it)return -1;
62         if(!valid_chan(it->dev,it->subdevice,it->chan))return -1;
63
64         it->maxdata=comedi_get_maxdata(it->dev,it->subdevice,it->chan);
65
66         /* check current range policy */
67         /* check n */
68
69         return 0;
70 }
71
72 int comedi_sv_measure(comedi_sv_t *it,double *data)
73 {
74         if(it->dev->subdevices[it->subdevice].subd_flags & SDF_LSAMPL){
75                 return sv_measure_l(it,data);
76         }else{
77                 return sv_measure_s(it,data);
78         }
79 }
80
81 int sv_measure_l(comedi_sv_t *it,double *data)
82 {
83         comedi_trig t;
84         int ret=0;
85         lsampl_t *val;
86         unsigned int chan;
87         comedi_range *rng;
88         double sum;
89         int i;
90         int n;
91
92         val=malloc(sizeof(*val)*it->n);
93
94         chan=CR_PACK(it->chan,it->range,it->aref);
95         
96         t.subdev=it->subdevice;
97         t.mode=0;
98         t.flags=TRIG_DITHER;
99         t.n_chan=1;
100         t.chanlist=&chan;
101         t.trigsrc=0;
102         t.trigvar=0;
103         t.trigvar1=0;
104
105         rng=comedi_get_range(it->dev,it->subdevice,it->chan,it->range);
106
107         for(n=0;n<it->n;){
108                 t.data=(void *)(val+n);
109                 t.n=it->n-n;
110                 i=ioctl_trigger(it->dev->fd,&t);
111                 if(i<=0){
112                         ret=i;
113                         goto out;
114                 }
115                 n+=i;
116         }
117
118         sum=0;
119         for(i=0;i<it->n;i++){
120                 sum+=comedi_to_phys(val[i],rng,it->maxdata);
121         }
122         *data=sum/it->n;
123
124 out:
125         free(val);
126
127         return ret;
128 }
129
130 /* yes, these functions are _almost_ exactly the same... */
131
132 int sv_measure_s(comedi_sv_t *it,double *data)
133 {
134         comedi_trig t;
135         int ret=0;
136         sampl_t *val;
137         unsigned int chan;
138         comedi_range *rng;
139         double sum;
140         int i;
141         int n;
142
143         val=malloc(sizeof(*val)*it->n);
144
145         chan=CR_PACK(it->chan,it->range,it->aref);
146         
147         t.subdev=it->subdevice;
148         t.mode=0;
149         t.flags=TRIG_DITHER;
150         t.n_chan=1;
151         t.chanlist=&chan;
152         t.data=val;
153         t.n=it->n;
154         t.trigsrc=0;
155         t.trigvar=0;
156         t.trigvar1=0;
157
158         rng=comedi_get_range(it->dev,it->subdevice,it->chan,it->range);
159
160         for(n=0;n<it->n;){
161                 t.data=val+n;
162                 t.n=it->n-n;
163                 i=ioctl_trigger(it->dev->fd,&t);
164                 if(i<=0){
165                         ret=i;
166                         goto out;
167                 }
168                 n+=i;
169         }
170
171         sum=0;
172         for(i=0;i<it->n;i++){
173                 sum+=comedi_to_phys(val[i],rng,it->maxdata);
174         }
175         *data=sum/it->n;
176
177 out:
178         free(val);
179
180         return ret;
181 }
182
183
184
185
186
187
188