diff --git a/adafruit_pca9685.py b/adafruit_pca9685.py index cc8cb0a..cc39f27 100755 --- a/adafruit_pca9685.py +++ b/adafruit_pca9685.py @@ -40,16 +40,27 @@ from adafruit_register.i2c_struct_array import StructArray from adafruit_bus_device import i2c_device +try: + from typing import Optional, Type + from types import TracebackType + from busio import I2C +except ImportError: + pass + class PWMChannel: - """A single PCA9685 channel that matches the :py:class:`~pwmio.PWMOut` API.""" + """A single PCA9685 channel that matches the :py:class:`~pwmio.PWMOut` API. + + :param PCA9685 pca: The PCA9685 object + :param int index: The index of the channel + """ - def __init__(self, pca, index): + def __init__(self, pca: "PCA9685", index: int): self._pca = pca self._index = index @property - def frequency(self): + def frequency(self) -> float: """The overall PWM frequency in Hertz (read-only). A PWMChannel's frequency cannot be set individually. All channels share a common frequency, set by PCA9685.frequency.""" @@ -60,7 +71,7 @@ def frequency(self, _): raise NotImplementedError("frequency cannot be set on individual channels") @property - def duty_cycle(self): + def duty_cycle(self) -> int: """16 bit value that dictates how much of one cycle is high (1) versus low (0). 0xffff will always be high, 0 will always be low and 0x7fff will be half high and then half low.""" pwm = self._pca.pwm_regs[self._index] @@ -69,7 +80,7 @@ def duty_cycle(self): return pwm[1] << 4 @duty_cycle.setter - def duty_cycle(self, value): + def duty_cycle(self, value: int) -> None: if not 0 <= value <= 0xFFFF: raise ValueError("Out of range") @@ -82,16 +93,19 @@ def duty_cycle(self, value): class PCAChannels: # pylint: disable=too-few-public-methods - """Lazily creates and caches channel objects as needed. Treat it like a sequence.""" + """Lazily creates and caches channel objects as needed. Treat it like a sequence. + + :param PCA9685 pca: The PCA9685 object + """ - def __init__(self, pca): + def __init__(self, pca: "PCA9685") -> None: self._pca = pca self._channels = [None] * len(self) - def __len__(self): + def __len__(self) -> int: return 16 - def __getitem__(self, index): + def __getitem__(self, index: int) -> PWMChannel: if not self._channels[index]: self._channels[index] = PWMChannel(self._pca, index) return self._channels[index] @@ -116,7 +130,13 @@ class PCA9685: prescale_reg = UnaryStruct(0xFE, " None: self.i2c_device = i2c_device.I2CDevice(i2c_bus, address) self.channels = PCAChannels(self) """Sequence of 16 `PWMChannel` objects. One for each channel.""" @@ -124,17 +144,17 @@ def __init__(self, i2c_bus, *, address=0x40, reference_clock_speed=25000000): """The reference clock speed in Hz.""" self.reset() - def reset(self): + def reset(self) -> None: """Reset the chip.""" self.mode1_reg = 0x00 # Mode1 @property - def frequency(self): + def frequency(self) -> float: """The overall PWM frequency in Hertz.""" return self.reference_clock_speed / 4096 / self.prescale_reg @frequency.setter - def frequency(self, freq): + def frequency(self, freq: float) -> None: prescale = int(self.reference_clock_speed / 4096.0 / freq + 0.5) if prescale < 3: raise ValueError("PCA9685 cannot output at the given frequency") @@ -146,12 +166,17 @@ def frequency(self, freq): # Mode 1, autoincrement on, fix to stop pca9685 from accepting commands at all addresses self.mode1_reg = old_mode | 0xA0 - def __enter__(self): + def __enter__(self) -> "PCA9685": return self - def __exit__(self, exception_type, exception_value, traceback): + def __exit__( + self, + exception_type: Optional[Type[type]], + exception_value: Optional[BaseException], + traceback: Optional[TracebackType], + ) -> None: self.deinit() - def deinit(self): + def deinit(self) -> None: """Stop using the pca9685.""" self.reset()