X-Git-Url: https://git.ayoreis.com/Adafruit_Blinka-hackapet.git/blobdiff_plain/de652f72b1884328ee22ec36deaa6320addd32e7..5690811c80a734fba26476512d82f3f69b13e816:/src/adafruit_blinka/microcontroller/mcp2221/mcp2221.py diff --git a/src/adafruit_blinka/microcontroller/mcp2221/mcp2221.py b/src/adafruit_blinka/microcontroller/mcp2221/mcp2221.py index 66d406d..665be7f 100644 --- a/src/adafruit_blinka/microcontroller/mcp2221/mcp2221.py +++ b/src/adafruit_blinka/microcontroller/mcp2221/mcp2221.py @@ -2,11 +2,13 @@ import os import time +import atexit + import hid # Here if you need it MCP2221_HID_DELAY = float(os.environ.get("BLINKA_MCP2221_HID_DELAY", 0)) -# Use to set delay between reset and device reopen +# Use to set delay between reset and device reopen. if negative, don't reset at all MCP2221_RESET_DELAY = float(os.environ.get("BLINKA_MCP2221_RESET_DELAY", 0.5)) # from the C driver @@ -51,12 +53,23 @@ class MCP2221: def __init__(self): self._hid = hid.device() self._hid.open(MCP2221.VID, MCP2221.PID) - self._reset() + # make sure the device gets closed before exit + atexit.register(self.close) + if MCP2221_RESET_DELAY >= 0: + self._reset() self._gp_config = [0x07] * 4 # "don't care" initial value for pin in range(4): self.gp_set_mode(pin, self.GP_GPIO) # set to GPIO mode self.gpio_set_direction(pin, 1) # set to INPUT + def close(self): + """Close the hid device. Does nothing if the device is not open.""" + self._hid.close() + + def __del__(self): + # try to close the device before destroying the instance + self.close() + def _hid_xfer(self, report, response=True): """Perform HID Transfer""" # first byte is report ID, which =0 for MCP2221 @@ -188,7 +201,7 @@ class MCP2221: # bus release will need "a few hundred microseconds" time.sleep(0.001) - # pylint: disable=too-many-arguments + # pylint: disable=too-many-arguments,too-many-branches def _i2c_write(self, cmd, address, buffer, start=0, end=None): if self._i2c_state() != 0x00: self._i2c_cancel() @@ -197,7 +210,7 @@ class MCP2221: length = end - start retries = 0 - while (end - start) > 0: + while (end - start) > 0 or not buffer: chunk = min(end - start, MCP2221_MAX_I2C_DATA_LEN) # write out current chunk resp = self._hid_xfer( @@ -222,6 +235,8 @@ class MCP2221: # yay chunk sent! while self._i2c_state() == RESP_I2C_PARTIALDATA: time.sleep(0.001) + if not buffer: + break start += chunk retries = 0 @@ -284,6 +299,8 @@ class MCP2221: continue if resp[2] in (RESP_READ_COMPL, RESP_READ_PARTIAL): break + else: + raise RuntimeError("I2C read error: max retries reached.") # move data into buffer chunk = min(end - start, 60) @@ -293,7 +310,7 @@ class MCP2221: # pylint: enable=too-many-arguments - def i2c_configure(self, baudrate=100000): + def _i2c_configure(self, baudrate=100000): """Configure I2C""" self._hid_xfer( bytes( @@ -324,7 +341,7 @@ class MCP2221: out_start=0, out_end=None, in_start=0, - in_end=None + in_end=None, ): """Write data from buffer_out to an address and then read data from an address and into buffer_in