/ adafruit_74hc595.py
adafruit_74hc595.py
1 # The MIT License (MIT) 2 # 3 # Copyright (c) 2018 Kattni Rembor for Adafruit Industries 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 `adafruit_74hc595` 24 ==================================================== 25 26 CircuitPython driver for 74HC595 shift register. 27 28 * Author(s): Kattni Rembor, Tony DiCola 29 30 Implementation Notes 31 -------------------- 32 33 **Hardware:** 34 35 "* `74HC595 Shift Register - 3 pack <https://www.adafruit.com/product/450>`_" 36 37 **Software and Dependencies:** 38 39 * Adafruit CircuitPython firmware for the supported boards: 40 https://github.com/adafruit/circuitpython/releases 41 42 * Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice 43 """ 44 45 import digitalio 46 import adafruit_bus_device.spi_device as spi_device 47 48 __version__ = "0.0.0-auto.0" 49 __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_74HC595.git" 50 51 52 class DigitalInOut: 53 """Digital input/output of the 74HC595. The interface is exactly the 54 same as the ``digitalio.DigitalInOut`` class, however note that by design 55 this device is OUTPUT ONLY! Attempting to read inputs or set 56 direction as input will raise an exception. 57 """ 58 59 def __init__(self, pin_number, shift_register_74hc595): 60 """Specify the pin number of the shift register (0...7) and 61 ShiftRegister74HC595 instance. 62 """ 63 self._pin = pin_number 64 self._shift_register = shift_register_74hc595 65 66 # kwargs in switch functions below are _necessary_ for compatibility 67 # with DigitalInout class (which allows specifying pull, etc. which 68 # is unused by this class). Do not remove them, instead turn off pylint 69 # in this case. 70 # pylint: disable=unused-argument 71 def switch_to_output(self, value=False, **kwargs): 72 """``DigitalInOut switch_to_output``""" 73 self.direction = digitalio.Direction.OUTPUT 74 self.value = value 75 76 def switch_to_input(self, **kwargs): # pylint: disable=no-self-use 77 """``switch_to_input`` is not supported.""" 78 raise RuntimeError("Digital input not supported.") 79 80 # pylint: enable=unused-argument 81 82 @property 83 def value(self): 84 """The value of the pin, either True for high or False for low.""" 85 return self._shift_register.gpio & (1 << self._pin) == (1 << self._pin) 86 87 @value.setter 88 def value(self, val): 89 gpio = self._shift_register.gpio 90 if val: 91 gpio |= 1 << self._pin 92 else: 93 gpio &= ~(1 << self._pin) 94 self._shift_register.gpio = gpio 95 96 @property 97 def direction(self): 98 """``Direction`` can only be set to ``OUTPUT``.""" 99 return digitalio.Direction.OUTPUT 100 101 @direction.setter 102 def direction(self, val): # pylint: disable=no-self-use 103 """``Direction`` can only be set to ``OUTPUT``.""" 104 if val != digitalio.Direction.OUTPUT: 105 raise RuntimeError("Digital input not supported.") 106 107 @property 108 def pull(self): 109 """Pull-up/down not supported, return None for no pull-up/down.""" 110 return None 111 112 @pull.setter 113 def pull(self, val): # pylint: disable=no-self-use 114 """Only supports null/no pull state.""" 115 if val is not None: 116 raise RuntimeError("Pull-up and pull-down not supported.") 117 118 119 class ShiftRegister74HC595: 120 """Initialise the 74HC595 on specified SPI bus.""" 121 122 def __init__(self, spi, latch): 123 self._device = spi_device.SPIDevice(spi, latch, baudrate=1000000) 124 self._gpio = bytearray(1) 125 self._gpio[0] = 0x00 126 127 @property 128 def gpio(self): 129 """The raw GPIO output register. Each bit represents the 130 output value of the associated pin (0 = low, 1 = high). 131 """ 132 return self._gpio[0] 133 134 @gpio.setter 135 def gpio(self, val): 136 self._gpio[0] = val & 0xFF 137 with self._device as spi: 138 # pylint: disable=no-member 139 spi.write(self._gpio) 140 141 def get_pin(self, pin): 142 """Convenience function to create an instance of the DigitalInOut class 143 pointing at the specified pin of this 74HC595 device . 144 """ 145 assert 0 <= pin <= 7 146 return DigitalInOut(pin, self)