ahio  1.0.0
I/O Communication Library
abstract_driver.py
Go to the documentation of this file.
1 # -*- coding: utf-8; -*-
2 #
3 # Copyright (c) 2016 Álan Crístoffer
4 #
5 # Permission is hereby granted, free of charge, to any person obtaining a copy
6 # of this software and associated documentation files (the "Software"), to deal
7 # in the Software without restriction, including without limitation the rights
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 # copies of the Software, and to permit persons to whom the Software is
10 # furnished to do so, subject to the following conditions:
11 #
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
14 #
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 # THE SOFTWARE.
22 
23 
27 
28 import ahio
29 
30 
31 
39  NAME = 'Driver name'
40  AVAILABLE = 'True if the driver is available, false otherwise'
41 
42 
43 
56 
57  _pin_mapping = {}
58  _pin_lin = {}
59 
60 
92  def available_pins(self):
93  raise NotImplementedMethod()
94 
95 
116  def map_pin(self, abstract_pin_id, physical_pin_id):
117  if physical_pin_id:
118  self._pin_mapping[abstract_pin_id] = physical_pin_id
119  else:
120  self._pin_mapping.pop(abstract_pin_id, None)
121 
122 
130  def mapped_pins(self):
131  return self._pin_mapping
132 
133  def _linear_interpolation(self, x, imin, imax, omin, omax):
134  return (imax * omin - imin * omax + x * (omax - omin)) / (imax - imin)
135 
136 
159  def set_pin_interpolation(self,
160  pin,
161  read_min,
162  read_max,
163  write_min,
164  write_max):
165  if type(pin) is list:
166  # I don't like breaking calls in multiple lines
167  args = (read_min, read_max, write_min, write_max)
168  for p in pin:
169  self.set_pin_interpolation(p, *args)
170  return
171 
172  valid_read = (read_min is not None and read_max is not None)
173  valid_write = (write_min is not None and write_max is not None)
174 
175  if not valid_read and not valid_write:
176  self._pin_lin.pop(pin, None)
177  return
178 
179  pin_id = self._pin_mapping.get(pin, None)
180  pins = [pin for pin in self.available_pins() if pin_id == pin['id']]
181  read = pins[0]['analog']['read_range']
182  write = pins[0]['analog']['write_range']
183  valid_read = valid_read and read
184  valid_write = valid_write and write
185  self._pin_lin[pin] = {
186  'read': (*read, read_min, read_max) if valid_read else None,
187  'write': (write_min, write_max, *write) if valid_write else None
188  }
189 
190 
207  def set_pin_direction(self, pin, direction):
208  if type(pin) is list:
209  for p in pin:
210  self.set_pin_direction(p, direction)
211  return
212 
213  pin_id = self._pin_mapping.get(pin, None)
214  if pin_id and type(direction) is ahio.Direction:
215  self._set_pin_direction(pin_id, direction)
216  else:
217  raise KeyError('Requested pin is not mapped: %s' % pin)
218 
219 
229  def pin_direction(self, pin):
230  if type(pin) is list:
231  return [self.pin_direction(p) for p in pin]
232 
233  pin_id = self._pin_mapping.get(pin, None)
234  if pin_id:
235  return self._pin_direction(pin_id)
236  else:
237  raise KeyError('Requested pin is not mapped: %s' % pin)
238 
239 
256  def set_pin_type(self, pin, ptype):
257  if type(pin) is list:
258  for p in pin:
259  self.set_pin_type(p, ptype)
260  return
261 
262  pin_id = self._pin_mapping.get(pin, None)
263  if type(ptype) is not ahio.PortType:
264  raise KeyError('ptype must be of type ahio.PortType')
265  elif pin_id:
266  self._set_pin_type(pin_id, ptype)
267  else:
268  raise KeyError('Requested pin is not mapped: %s' % pin)
269 
270 
280  def pin_type(self, pin):
281  if type(pin) is list:
282  return [self.pin_type(p) for p in pin]
283 
284  pin_id = self._pin_mapping.get(pin, None)
285  if pin_id:
286  return self._pin_type(pin_id)
287  else:
288  raise KeyError('Requested pin is not mapped: %s' % pin)
289 
290 
315  def write(self, pin, value, pwm=False):
316  if type(pin) is list:
317  for p in pin:
318  self.write(p, value, pwm)
319  return
320 
321  if pwm and type(value) is not int and type(value) is not float:
322  raise TypeError('pwm is set, but value is not a float or int')
323 
324  pin_id = self._pin_mapping.get(pin, None)
325  if pin_id:
326  lpin = self._pin_lin.get(pin, None)
327  if lpin and type(lpin['write']) is tuple:
328  write_range = lpin['write']
329  value = self._linear_interpolation(value, *write_range)
330  self._write(pin_id, value, pwm)
331  else:
332  raise KeyError('Requested pin is not mapped: %s' % pin)
333 
334 
348  def read(self, pin):
349  if type(pin) is list:
350  return [self.read(p) for p in pin]
351 
352  pin_id = self._pin_mapping.get(pin, None)
353  if pin_id:
354  value = self._read(pin_id)
355  lpin = self._pin_lin.get(pin, None)
356  if lpin and type(lpin['read']) is tuple:
357  read_range = lpin['read']
358  value = self._linear_interpolation(value, *read_range)
359  return value
360  else:
361  raise KeyError('Requested pin is not mapped: %s' % pin)
362 
363 
371  def analog_references(self):
372  raise NotImplementedMethod()
373 
374 
395  def set_analog_reference(self, reference, pin=None):
396  if pin is None:
397  self._set_analog_reference(reference, None)
398  else:
399  pin_id = self._pin_mapping.get(pin, None)
400  if pin_id:
401  self._set_analog_reference(reference, pin_id)
402  else:
403  raise KeyError('Requested pin is not mapped: %s' % pin)
404 
405 
424  def analog_reference(self, pin=None):
425  if pin is None:
426  return self._analog_reference(None)
427  else:
428  pin_id = self._pin_mapping.get(pin, None)
429  if pin_id:
430  return self._analog_reference(pin_id)
431  else:
432  raise KeyError('Requested pin is not mapped: %s' % pin)
433 
434 
453  def set_pwm_frequency(self, frequency, pin=None):
454  if pin is None:
455  self._set_pwm_frequency(frequency, None)
456  else:
457  pin_id = self._pin_mapping.get(pin, None)
458  if pin_id:
459  self._set_pwm_frequency(frequency, pin_id)
460  else:
461  raise KeyError('Requested pin is not mapped: %s' % pin)
def map_pin(self, abstract_pin_id, physical_pin_id)
Maps a pin number to a physical device pin.
def set_pin_interpolation(self, pin, read_min, read_max, write_min, write_max)
Interpolates input and output values for pin.
def available_pins(self)
Returns available pins.
def set_pwm_frequency(self, frequency, pin=None)
Sets PWM frequency, if supported by hardware.
def _linear_interpolation(self, x, imin, imax, omin, omax)
def analog_references(self)
Possible values for analog reference.
def pin_direction(self, pin)
Gets the ahio.Direction this pin was set to.
def mapped_pins(self)
Returns a dictionary containing the mapped pins.
def set_pin_type(self, pin, ptype)
Sets pin pin to type.
def set_analog_reference(self, reference, pin=None)
Sets the analog reference to reference
Abstract class containing information about the driver.
def pin_type(self, pin)
Gets the ahio.PortType this pin was set to.
def write(self, pin, value, pwm=False)
Sets the output to the given value.
def analog_reference(self, pin=None)
Returns the analog reference.
def read(self, pin)
Reads value from pin pin.
def set_pin_direction(self, pin, direction)
Sets pin pin to direction.