command: Fix except declaration for get_comedi_cmd_pointer
[pycomedi.git] / pycomedi / instruction.pyx
1 # Copyright (C) 2011-2012 W. Trevor King <wking@tremily.us>
2 #
3 # This file is part of pycomedi.
4 #
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
8 # version.
9 #
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.
13 #
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/>.
16
17 "Wrap Comedi's `comedi_insn` struct in the `Insn` class"
18
19 cimport libc.stdlib as _stdlib
20 import numpy as _numpy
21
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
27
28
29 cdef class Insn (object):
30     """A Comedi instruction
31
32     >>> from .constant import INSN, AREF
33     >>> i = Insn()
34     >>> print str(i)
35         insn: read
36         data: []
37       subdev: 0
38     chanspec: <ChanSpec chan:0 range:0 aref:ground flags:->
39     >>> i.insn = INSN.write
40
41     `data` takes any iterable that supports `length()` and returns NumPy arrays.
42
43     >>> i.data = [1, 2, 3]
44     >>> type(i.data)
45     <type 'numpy.ndarray'>
46
47     `subdev` is currently just an integer (not a `Subdevice` instance).
48
49     >>> i.subdev = 3
50     >>> i.subdev
51     3
52     >>> type(i.subdev)
53     <type 'int'>
54
55     Because `ChanSpec` instances store their value internally (not
56     using the value stored in the `Insn` instance), direct operations
57     on them have no effect on the intruction.
58
59     >>> i.chanspec.aref = AREF.diff
60     >>> i.chanspec
61     <ChanSpec chan:0 range:0 aref:ground flags:->
62
63     To have an effect, you need to explicity set the `chanspec` attribute:
64
65     >>> c = i.chanspec
66     >>> c.aref = AREF.diff
67     >>> i.chanspec = c
68     >>> i.chanspec
69     <ChanSpec chan:0 range:0 aref:diff flags:->
70
71     >>> print str(i)
72         insn: write
73         data: [1 2 3]
74       subdev: 3
75     chanspec: <ChanSpec chan:0 range:0 aref:diff flags:->
76     """
77     def __cinit__(self):
78         self._insn.insn = _constant.INSN.read.value
79         self._insn.data = NULL
80         self._fields = ['insn', 'data', 'subdev', 'chanspec']
81
82     def __dealloc__(self):
83         if self._insn.data is not NULL:
84             _stdlib.free(self._insn.data)
85
86     cdef _comedi_h.comedi_insn get_comedi_insn(self):
87         return self._insn
88
89     def __str__(self):
90         max_field_length = max([len(f) for f in self._fields])
91         lines = []
92         for f in self._fields:
93             lines.append('%*s: %s' % (max_field_length, f, getattr(self, f)))
94         return '\n'.join(lines)
95
96     def _insn_get(self):
97         return _constant.INSN.index_by_value(self._insn.insn)
98     def _insn_set(self, value):
99         self._insn.insn = _constant.bitwise_value(value)
100     insn = property(fget=_insn_get, fset=_insn_set)
101
102     def _data_get(self):
103         data = _numpy.ndarray(shape=(self._insn.n,), dtype=_numpy.uint)
104         # TODO: point into existing data array?
105         for i in range(self._insn.n):
106             data[i] = self._insn.data[i]
107         return data
108     def _data_set(self, value):
109         if self._insn.data is not NULL:
110             _stdlib.free(self._insn.data)
111         self._insn.n = len(value)
112         self._insn.data = <_comedi_h.lsampl_t *>_stdlib.malloc(
113             self._insn.n*sizeof(_comedi_h.lsampl_t))
114         if self._insn.data is NULL:
115             self._insn.n = 0
116             raise _PyComediError('out of memory?')
117         for i,x in enumerate(value):
118             self._insn.data[i] = x
119     data = property(fget=_data_get, fset=_data_set)
120
121     def _subdev_get(self):
122         return int(self._insn.subdev)
123     def _subdev_set(self, value):
124         self._insn.subdev = value
125     subdev = property(fget=_subdev_get, fset=_subdev_set)
126
127     def _chanspec_get(self):
128         c = _chanspec.ChanSpec()
129         c.value = self._insn.chanspec
130         return c
131     def _chanspec_set(self, value):
132         self._insn.chanspec = _constant.bitwise_value(value)
133     chanspec = property(fget=_chanspec_get, fset=_chanspec_set)