Versioning started.
[pycomedi.git] / pycomedi / comedi_single_dio.py
1 """Use Comedi drivers for single-shot digital input/output
2
3 Being single-shot implementations, read/writes will be software timed,
4 so this module would not be a good choice if you need millisecond
5 resolution.  However, it does provide a simple and robust way to
6 generate/aquire signals at 1 second and greater timescales.
7 """
8
9 import comedi as c
10
11 VERSION = 0.0
12
13 class dioError (Exception) :
14     "Digital IO error"
15     pass
16
17 class dio_obj :
18     def __init__(self, filename="/dev/comedi0", subdevice=2, chan=(0,1,2,3), aref=0, range=0, output=True) :
19         self.filename = filename
20         self.subdev = subdevice
21         self.chan = chan
22         self.aref = aref
23         self.range = range
24         self.output = output
25         self.dev = c.comedi_open(filename)
26         if self.dev < 0 :
27             raise dioError, "Cannot open %s" % self.filename
28         type = c.comedi_get_subdevice_type(self.dev, self.subdev)
29         if type != c.COMEDI_SUBD_DIO :
30             raise dioError, "Comedi subdevice %d has wrong type %d" % (self.subdev, type)
31         if self.output :
32             self.set_to_output()
33         else :
34             self.set_to_input()
35     def set_to_output(self) :
36         for chan in self.chan :
37             rc = c.comedi_dio_config(self.dev, self.subdev, chan, c.COMEDI_OUTPUT)
38             if rc != 1 : # yes, comedi_dio_config returns 1 on success, -1 on failure, as of comedilib-0.8.1
39                 raise dioError, 'comedi_dio_config("%s", %d, %d, %d) returned %d' % (self.filename, self.subdev, chan, c.COMEDI_OUTPUT, rc)
40         self.output = True
41     def set_to_input(self) :
42         for chan in self.chan :
43             rc = c.comedi_dio_config(self.dev, self.subdev, chan, c.COMEDI_INPUT)
44             if rc != 1 :
45                 raise dioError, 'comedi_dio_config("%s", %d, %d, %d) returned %d' % (self.filename, self.subdev, chan, c.COMEDI_INPUT, rc)
46         self.output = False
47     def write_chan_index(self, chan_index, data) :
48         if self.output != True :
49             raise dioError, "Must be an output to write"
50         rc = c.comedi_data_write(self.dev, self.subdev, self.chan[chan_index], self.range, self.aref, data);
51         if rc != 1 : # the number of samples written
52             raise dioError, "comedi_data_write returned %d" % rc
53     def read_chan_index(self, chan_index) :
54         if self.output == True :
55             raise dioError, "Must be an input to read"
56         rc, data = c.comedi_data_read(self.dev, self.subdev, self.chan[chan_index], self.range, self.aref);
57         if rc != 1 : # the number of samples read
58             raise dioError, "comedi_data_read returned %d" % rc
59         return data
60     def write_port(self, data) :
61         "Channel significance increases with array index"
62         for i in range(len(self.chan)) :
63             self.write_chan_index(i, (data >> i) % 2)
64     def read_port(self) :
65         data = 0
66         for i in range(len(self.chan)) :
67             data += self.read_chan_index(i) << i
68         return data
69
70 class write_dig_port (dio_obj) :
71     def __call__(self, data) :
72         self.write_port(data)
73
74 def _test_dio_obj() :
75     d = dio_obj()
76     d.set_to_output()
77     d.write_chan_index(0, 1)
78     d.write_chan_index(0, 0)
79     d.write_port(7)
80     d.set_to_input()
81     data = d.read_chan_index(0)
82     print "channel %d is %d" % (d.chan[0], data)
83     data = d.read_port()
84     print "port value is %d" % data
85     print "dio_obj success"
86
87 def _test_write_dig_port() :
88     p = write_dig_port()
89     for data in [0, 1, 2, 3, 4, 5, 6, 7] :
90         p(data)
91     print "write_dig_port success"
92
93 def test() :
94     _test_dio_obj()
95     _test_write_dig_port()
96
97 if __name__ == "__main__" :
98     test()