1 # Copyright (C) 2011-2012 W. Trevor King <wking@tremily.us>
3 # This file is part of pycomedi.
5 # pycomedi is free software: you can redistribute it and/or modify it under the
6 # terms of the GNU General Public License as published by the Free Software
7 # Foundation, either version 2 of the License, or (at your option) any later
10 # pycomedi is distributed in the hope that it will be useful, but WITHOUT ANY
11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License along with
15 # pycomedi. If not, see <http://www.gnu.org/licenses/>.
17 "Wrap Comedi's `comedi_cmd` struct in the `Command` class"
19 cimport libc.stdlib as _stdlib
20 import numpy as _numpy
22 from pycomedi cimport _comedi_h
23 from pycomedi cimport _comedilib_h
24 from . import PyComediError as _PyComediError
25 from . import chanspec as _chanspec
26 from . import constant as _constant
29 cdef class Command (object):
32 >>> from .constant import AREF, CMDF, TRIG_SRC
33 >>> from .channel import AnalogChannel
34 >>> from .chanspec import ChanSpec
35 >>> from .device import Device
54 `data` takes any iterable that supports `length()` and returns NumPy arrays.
56 >>> c.data = [1, 2, 3]
58 <type 'numpy.ndarray'>
60 `subdev` is currently just an integer (not a `Subdevice` instance).
68 `flags` and trigger sources return `FlagValue` instances.
70 >>> c.flags # doctest: +ELLIPSIS
71 <pycomedi.constant.FlagValue object at 0x...>
72 >>> c.flags = CMDF.priority | CMDF.write
74 >>> c.start_src # doctest: +ELLIPSIS
75 <pycomedi.constant.FlagValue object at 0x...>
76 >>> c.start_src = TRIG_SRC.int | TRIG_SRC.now
77 >>> c.scan_begin_src = TRIG_SRC.timer
78 >>> c.scan_begin_arg = 10
79 >>> c.convert_src = TRIG_SRC.now
80 >>> c.scan_end_src = TRIG_SRC.count
81 >>> c.scan_end_arg = 4
82 >>> c.stop_src = TRIG_SRC.none
84 Because `ChanSpec` instances store their value internally (not
85 using the value stored in the `Command` instance), direct
86 operations on them have no effect on the intruction.
89 ... ChanSpec(chan=0, aref=AREF.diff),
90 ... ChanSpec(chan=1, aref=AREF.diff),
92 >>> c.chanlist = chanlist
94 <ChanSpec chan:0 range:0 aref:diff flags:->
95 >>> c.chanlist[0].aref = AREF.ground
97 <ChanSpec chan:0 range:0 aref:diff flags:->
99 To have an effect, you need to explicity set the `chanlist` attribute:
101 >>> chanlist = c.chanlist
102 >>> chanlist[0].aref = AREF.ground
103 >>> c.chanlist = chanlist
105 <ChanSpec chan:0 range:0 aref:ground flags:->
107 You can also set chanspec items with `AnalogChannel` instances (or
108 any object that has a `chanspec` method).
110 >>> d = Device('/dev/comedi0')
112 >>> subdevice = d.get_read_subdevice()
113 >>> c.chanlist = [subdevice.channel(1, factory=AnalogChannel,
119 flags: priority|write
122 scan_begin_src: timer
130 chanlist: [<ChanSpec chan:1 range:0 aref:diff flags:->]
134 self._cmd.chanlist = NULL
135 self._cmd.data = NULL
137 'subdev', 'flags', 'start_src', 'start_arg', 'scan_begin_src',
138 'scan_begin_arg', 'convert_src', 'convert_arg', 'scan_end_src',
139 'scan_end_arg', 'stop_src', 'stop_arg', 'chanlist', 'data']
141 def __dealloc__(self):
142 if self._cmd.chanlist is not NULL:
143 _stdlib.free(self._cmd.chanlist)
144 if self._cmd.data is not NULL:
145 _stdlib.free(self._cmd.data)
147 cdef _comedi_h.comedi_cmd *get_comedi_cmd_pointer(self) except *:
151 max_field_length = max([len(f) for f in self._fields])
153 for f in self._fields:
154 lines.append('%*s: %s' % (max_field_length, f, getattr(self, f)))
155 return '\n'.join(lines)
157 def _subdev_get(self):
158 return self._cmd.subdev
159 def _subdev_set(self, value):
160 self._cmd.subdev = _constant.bitwise_value(value)
161 subdev = property(fget=_subdev_get, fset=_subdev_set)
163 def _flags_get(self):
164 return _constant.FlagValue(_constant.CMDF, self._cmd.flags)
165 def _flags_set(self, value):
166 self._cmd.flags = _constant.bitwise_value(value)
167 flags = property(fget=_flags_get, fset=_flags_set)
169 def _start_src_get(self):
170 return _constant.FlagValue(_constant.TRIG_SRC, self._cmd.start_src)
171 def _start_src_set(self, value):
172 self._cmd.start_src = _constant.bitwise_value(value)
173 start_src = property(fget=_start_src_get, fset=_start_src_set)
175 def _start_arg_get(self):
176 return self._cmd.start_arg
177 def _start_arg_set(self, value):
178 self._cmd.start_arg = value
179 start_arg = property(fget=_start_arg_get, fset=_start_arg_set)
181 def _scan_begin_src_get(self):
182 return _constant.FlagValue(_constant.TRIG_SRC, self._cmd.scan_begin_src)
183 def _scan_begin_src_set(self, value):
184 self._cmd.scan_begin_src = _constant.bitwise_value(value)
185 scan_begin_src = property(fget=_scan_begin_src_get, fset=_scan_begin_src_set)
187 def _scan_begin_arg_get(self):
188 return self._cmd.scan_begin_arg
189 def _scan_begin_arg_set(self, value):
190 self._cmd.scan_begin_arg = value
191 scan_begin_arg = property(fget=_scan_begin_arg_get, fset=_scan_begin_arg_set)
193 def _convert_src_get(self):
194 return _constant.FlagValue(_constant.TRIG_SRC, self._cmd.convert_src)
195 def _convert_src_set(self, value):
196 self._cmd.convert_src = _constant.bitwise_value(value)
197 convert_src = property(fget=_convert_src_get, fset=_convert_src_set)
199 def _convert_arg_get(self):
200 return self._cmd.convert_arg
201 def _convert_arg_set(self, value):
202 self._cmd.convert_arg = value
203 convert_arg = property(fget=_convert_arg_get, fset=_convert_arg_set)
206 def _scan_end_src_get(self):
207 return _constant.FlagValue(_constant.TRIG_SRC, self._cmd.scan_end_src)
208 def _scan_end_src_set(self, value):
209 self._cmd.scan_end_src = _constant.bitwise_value(value)
210 scan_end_src = property(fget=_scan_end_src_get, fset=_scan_end_src_set)
212 def _scan_end_arg_get(self):
213 return self._cmd.scan_end_arg
214 def _scan_end_arg_set(self, value):
215 self._cmd.scan_end_arg = value
216 scan_end_arg = property(fget=_scan_end_arg_get, fset=_scan_end_arg_set)
218 def _stop_src_get(self):
219 return _constant.FlagValue(_constant.TRIG_SRC, self._cmd.stop_src)
220 def _stop_src_set(self, value):
221 self._cmd.stop_src = _constant.bitwise_value(value)
222 stop_src = property(fget=_stop_src_get, fset=_stop_src_set)
224 def _stop_arg_get(self):
225 return self._cmd.stop_arg
226 def _stop_arg_set(self, value):
227 self._cmd.stop_arg = value
228 stop_arg = property(fget=_stop_arg_get, fset=_stop_arg_set)
230 def _chanlist_get(self):
232 for i in range(self._cmd.chanlist_len):
233 c = _chanspec.ChanSpec()
234 c.value = self._cmd.chanlist[i]
237 def _chanlist_set(self, value):
238 if self._cmd.chanlist is not NULL:
239 _stdlib.free(self._cmd.chanlist)
240 self._cmd.chanlist_len = len(value)
241 self._cmd.chanlist = <unsigned int *>_stdlib.malloc(
242 self._cmd.chanlist_len*sizeof(unsigned int))
243 if self._cmd.chanlist is NULL:
244 self._cmd.chanlist_len = 0
245 raise _PyComediError('out of memory?')
246 for i,x in enumerate(value):
247 if hasattr(x, 'chanspec'):
249 self._cmd.chanlist[i] = _constant.bitwise_value(x)
250 chanlist = property(fget=_chanlist_get, fset=_chanlist_set)
253 data = _numpy.ndarray(shape=(self._cmd.data_len,), dtype=_numpy.uint16)
254 # TODO: point into existing data array?
255 for i in range(self._cmd.data_len):
256 data[i] = self._cmd.data[i]
258 def _data_set(self, value):
259 if self._cmd.data is not NULL:
260 _stdlib.free(self._cmd.data)
261 self._cmd.data_len = len(value)
262 self._cmd.data = <_comedi_h.sampl_t *>_stdlib.malloc(
263 self._cmd.data_len*sizeof(_comedi_h.sampl_t))
264 if self._cmd.data is NULL:
265 self._cmd.data_len = 0
266 raise _PyComediError('out of memory?')
267 for i,x in enumerate(value):
268 self._cmd.data[i] = x
269 data = property(fget=_data_get, fset=_data_set)