AFM.stepper_approach should only call figure.show if it exits.
[pyafm.git] / pyafm / digital_port.py
1 # Copyright (C) 2012 W. Trevor King <wking@tremily.us>
2 #
3 # This file is part of pyafm.
4 #
5 # pyafm 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 3 of the License, or (at your option) any later
8 # version.
9 #
10 # pyafm 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 # pyafm.  If not, see <http://www.gnu.org/licenses/>.
16
17 from pycomedi.channel import DigitalChannel as _DigitalChannel
18 import pypiezo.base as _base
19
20
21 class DigitalPort (object):
22     """A digital input/output port (i.e. cluster of channels).
23
24     >>> from pyafm.config import DigitalPortConfig
25
26     >>> devices = []
27
28     >>> config = DigitalPortConfig()
29     >>> config['channels'] = [1, 2, 3, 4]
30     >>> config['name'] = 'test port'
31
32     >>> port = DigitalPort(config=config)
33     >>> port.load_from_config(devices=devices)
34     >>> port.write_bitfield(13)
35     >>> port.write([1, 0, 1, 0])
36     >>> port.write_bitfield(0)
37
38     >>> for device in devices:
39     ...     device.close()
40     """
41     def __init__(self, config):
42         self.config = config
43         self.subdevice = None
44
45     def load_from_config(self, devices):
46         c = self.config  # reduce verbosity
47         if self.subdevice is None:
48             device = _base.load_device(filename=c['device'], devices=devices)
49             if c['subdevice'] < 0:
50                 self.subdevice = device.find_subdevice_by_type(
51                     c['subdevice-type'])
52             else:
53                 self.subdevice = device.subdevice(index=c['subdevice'])
54             self.channels = []
55             self.write_mask = 0
56             for index in c['channels']:
57                 channel = self.subdevice.channel(
58                     index=index, factory=_DigitalChannel)
59                 channel.dio_config(c['direction'])
60                 self.write_mask |= 1 << index
61                 self.channels.append(channel)
62         self.name = c['name']
63
64     def setup_config(self):
65         self.config['device'] = self.subdevice.device.filename
66         self.config['subdevice'] = self.subdevice.index
67         self.config['channels'] = [c.index for c in self.channels]
68         if self.channels:
69             self.config['direction'] = self.channels[0].dio_get_config()
70
71     def write(self, values):
72         value = 0
73         for channel,val in zip(self.channels, values):
74             value &= val * (1 << channel.index)
75         self.write_bitfield(value)
76
77     def write_bitfield(self, value):
78         self.subdevice.dio_bitfield(bits=value, write_mask=self.write_mask)