from ds
[comedilib.git] / lib / dio.c
1 /*
2     lib/dio.c
3     digital I/O routines
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 <errno.h>
32 #include <comedi.h>
33 #include <string.h>
34
35 #include <libinternal.h>
36
37
38 int comedi_dio_config(comedi_t *it,unsigned int subdev,unsigned int chan,unsigned int io)
39 {
40         subdevice *s;
41
42         if(!valid_chan(it,subdev,chan))
43                 return -1;
44         
45         s=it->subdevices+subdev;
46         if(s->type!=COMEDI_SUBD_DIO)
47                 return -1;
48
49         if(io!=COMEDI_INPUT && io!=COMEDI_OUTPUT)
50                 return -1;
51
52         if(it->has_insnlist_ioctl){
53                 comedi_insn insn;
54                 lsampl_t data;
55                 
56                 memset(&insn,0,sizeof(insn));
57                 insn.insn = INSN_CONFIG;
58                 insn.n = 1;
59                 insn.data = &data;
60                 insn.subdev = subdev;
61                 insn.chanspec = CR_PACK(chan,0,0);
62                 data=io;
63
64                 return comedi_do_insn(it,&insn);
65         }else
66         {
67                 comedi_trig trig;
68                 lsampl_t data=io;
69
70                 memset(&trig,0,sizeof(trig));
71                 trig.flags=TRIG_CONFIG|TRIG_WRITE;
72                 trig.n_chan=1;
73                 trig.n=1;
74                 trig.subdev=subdev;
75                 trig.chanlist=&chan;
76                 trig.data=(sampl_t *)&data;
77
78                 return comedi_trigger(it,&trig);
79         }
80 }
81
82 int comedi_dio_read(comedi_t *it,unsigned int subdev,unsigned int chan,
83         unsigned int *val)
84 {
85         subdevice *s;
86         int ret;
87
88         if(!valid_chan(it,subdev,chan))
89                 return -1;
90
91         s = it->subdevices+subdev;
92         if(s->type!=COMEDI_SUBD_DIO &&
93            s->type!=COMEDI_SUBD_DO &&
94            s->type!=COMEDI_SUBD_DI)
95                 return -1;
96
97         if(it->has_insnlist_ioctl){
98                 comedi_insn insn;
99                 lsampl_t data;
100                 
101                 memset(&insn,0,sizeof(insn));
102                 insn.insn = INSN_READ;
103                 insn.n = 1;
104                 insn.data = &data;
105                 insn.subdev = subdev;
106                 insn.chanspec = CR_PACK(chan,0,0);
107
108                 ret = comedi_do_insn(it,&insn);
109
110                 *val = data;
111
112                 return ret;
113         }else{
114                 comedi_trig trig;
115                 lsampl_t data;
116
117                 memset(&trig,0,sizeof(trig));
118                 trig.n_chan=1;
119                 trig.n=1;
120                 trig.subdev=subdev;
121                 trig.chanlist=&chan;
122                 trig.data=(sampl_t *)&data;
123
124                 ret=comedi_trigger(it,&trig);
125
126                 if(ret>=0 && val)*val=data;
127
128                 return ret;
129         }
130 }
131
132 int comedi_dio_write(comedi_t *it,unsigned int subdev,unsigned int chan,
133         unsigned int val)
134 {
135         subdevice *s;
136
137         if(!valid_chan(it,subdev,chan))
138                 return -1;
139         
140         s = it->subdevices+subdev;
141         if(s->type!=COMEDI_SUBD_DIO &&
142            s->type!=COMEDI_SUBD_DO)
143                 return -1;
144
145         if(it->has_insnlist_ioctl){
146                 comedi_insn insn;
147                 lsampl_t data;
148                 
149                 memset(&insn,0,sizeof(insn));
150                 insn.insn = INSN_WRITE;
151                 insn.n = 1;
152                 insn.data = &data;
153                 insn.subdev = subdev;
154                 insn.chanspec = CR_PACK(chan,0,0);
155
156                 data = val;
157
158                 return comedi_do_insn(it,&insn);
159         }else{
160                 comedi_trig trig;
161                 lsampl_t data;
162
163                 data=val;
164
165                 memset(&trig,0,sizeof(trig));
166                 trig.n_chan=1;
167                 trig.n=1;
168                 trig.flags=TRIG_WRITE;
169                 trig.subdev=subdev;
170                 trig.chanlist=&chan;
171                 trig.data=(sampl_t *)&data;
172
173                 return comedi_trigger(it,&trig);
174         }
175 }
176
177 int comedi_dio_bitfield(comedi_t *it,unsigned int subdev,unsigned int mask,unsigned int *bits)
178 {
179         int ret;
180         unsigned int m,bit;
181         subdevice *s;
182
183         if(!valid_subd(it,subdev))
184                 return -1;
185
186         s=it->subdevices+subdev;
187
188         if(s->type!=COMEDI_SUBD_DIO && s->type!=COMEDI_SUBD_DO &&
189            s->type!=COMEDI_SUBD_DI)
190                 return -1;
191
192         if(s->has_insn_bits){
193                 comedi_insn insn;
194                 lsampl_t data[2];
195                 
196                 memset(&insn,0,sizeof(insn));
197
198                 insn.insn = INSN_BITS;
199                 insn.n = 2;
200                 insn.data = data;
201                 insn.subdev = subdev;
202
203                 data[0]=mask;
204                 data[1]=*bits;
205
206                 ret = comedi_do_insn(it,&insn);
207
208                 if(ret<0)return ret;
209
210                 *bits = data[1];
211
212                 return 0;
213         }else{
214                 unsigned int i,n_chan;
215
216                 n_chan=comedi_get_n_channels(it,subdev);
217                 if(n_chan>32)n_chan=32;
218                 for(i=0,m=1;i<n_chan;i++,m<<=1){
219                         if(mask&m){
220                                 bit=(*bits&m)?1:0;
221                                 ret=comedi_dio_write(it,subdev,i,bit);
222                         }else{
223                                 ret=comedi_dio_read(it,subdev,i,&bit);
224                                 if(bit) *bits|=m;
225                                 else (*bits)&=~m;
226                         }
227                         if(ret<0)return ret;
228                 }
229                 return (int)n_chan;
230         }
231 }
232