From 5ddaf451154503fb12d9e8b76e9b44f34adeeef6 Mon Sep 17 00:00:00 2001 From: Liz Date: Tue, 14 Nov 2023 10:33:37 -0500 Subject: [PATCH 1/4] update for gain setting --- .pylintrc | 43 ++------------- README.rst | 3 +- adafruit_ad569x.py | 132 +++++++++++++++++++++------------------------ docs/conf.py | 1 - requirements.txt | 1 - 5 files changed, 65 insertions(+), 115 deletions(-) diff --git a/.pylintrc b/.pylintrc index 322d61e..f945e92 100644 --- a/.pylintrc +++ b/.pylintrc @@ -26,7 +26,7 @@ jobs=1 # List of plugins (as comma separated values of python modules names) to load, # usually to register additional checkers. -load-plugins= +load-plugins=pylint.extensions.no_self_use # Pickle collected data for later comparisons. persistent=yes @@ -54,8 +54,8 @@ confidence= # --enable=similarities". If you want to run only the classes checker, but have # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" -# disable=import-error,print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call -disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error,bad-continuation,pointless-string-statement,unspecified-encoding +# disable=import-error,raw-checker-failed,bad-inline-option,locally-disabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,deprecated-str-translate-call +disable=raw-checker-failed,bad-inline-option,locally-disabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,import-error,pointless-string-statement,unspecified-encoding # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option @@ -225,12 +225,6 @@ max-line-length=100 # Maximum number of lines in a module max-module-lines=1000 -# List of optional constructs for which whitespace checking is disabled. `dict- -# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. -# `trailing-comma` allows a space between comma and closing bracket: (a, ). -# `empty-line` allows space-only lines. -no-space-check=trailing-comma,dict-separator - # Allow the body of a class to be on the same line as the declaration if body # contains single statement. single-line-class-stmt=no @@ -257,38 +251,22 @@ min-similarity-lines=12 [BASIC] -# Naming hint for argument names -argument-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - # Regular expression matching correct argument names argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ -# Naming hint for attribute names -attr-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - # Regular expression matching correct attribute names attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ # Bad variable names which should always be refused, separated by a comma bad-names=foo,bar,baz,toto,tutu,tata -# Naming hint for class attribute names -class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ - # Regular expression matching correct class attribute names class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ -# Naming hint for class names -# class-name-hint=[A-Z_][a-zA-Z0-9]+$ -class-name-hint=[A-Z_][a-zA-Z0-9_]+$ - # Regular expression matching correct class names # class-rgx=[A-Z_][a-zA-Z0-9]+$ class-rgx=[A-Z_][a-zA-Z0-9_]+$ -# Naming hint for constant names -const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ - # Regular expression matching correct constant names const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ @@ -296,9 +274,6 @@ const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ # ones are exempt. docstring-min-length=-1 -# Naming hint for function names -function-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - # Regular expression matching correct function names function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ @@ -309,21 +284,12 @@ good-names=r,g,b,w,i,j,k,n,x,y,z,ex,ok,Run,_ # Include a hint for the correct naming format with invalid-name include-naming-hint=no -# Naming hint for inline iteration names -inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ - # Regular expression matching correct inline iteration names inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ -# Naming hint for method names -method-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - # Regular expression matching correct method names method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ -# Naming hint for module names -module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ - # Regular expression matching correct module names module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ @@ -339,9 +305,6 @@ no-docstring-rgx=^_ # to this list to register other decorators that produce valid properties. property-classes=abc.abstractproperty -# Naming hint for variable names -variable-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - # Regular expression matching correct variable names variable-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ diff --git a/README.rst b/README.rst index 4edaa5e..f79ad31 100644 --- a/README.rst +++ b/README.rst @@ -30,7 +30,6 @@ This driver depends on: * `Adafruit CircuitPython `_ * `Bus Device `_ -* `Register `_ Please ensure all dependencies are available on the CircuitPython filesystem. This is easily achieved by downloading @@ -84,7 +83,7 @@ following command to install: .. code-block:: shell - circup install ad569x + circup install adafruit--circuitpython-ad569x Or the following command to update an existing version: diff --git a/adafruit_ad569x.py b/adafruit_ad569x.py index 3622acd..7ef0efc 100644 --- a/adafruit_ad569x.py +++ b/adafruit_ad569x.py @@ -35,7 +35,6 @@ from micropython import const from adafruit_bus_device.i2c_device import I2CDevice -from adafruit_register.i2c_bits import RWBits try: import typing # pylint: disable=unused-import @@ -47,18 +46,9 @@ __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_AD569x.git" _NOP = const(0x00) -_WRITE_INPUT = const(0x10) -_UPDATE_DAC = const(0x20) _WRITE_DAC_AND_INPUT = const(0x30) _WRITE_CONTROL = const(0x40) -NORMAL_MODE = const(0x00) -OUTPUT_1K_IMPEDANCE = const(0x01) -OUTPUT_100K_IMPEDANCE = const(0x02) -OUTPUT_TRISTATE = const(0x03) -GAIN_1X = const(0) -GAIN_2X = const(1) - class Adafruit_AD569x: """Class which provides interface to AD569x Dac.""" @@ -75,18 +65,20 @@ def __init__(self, i2c: I2C, address: int = 0x4C) -> None: :param address: The I2C address of the device. Defaults to 0x4C. """ self.i2c_device = I2CDevice(i2c, address) - self._address = address - - self._reset_command = RWBits(1, _WRITE_CONTROL, 15, 2) - self._mode_command = RWBits(2, _WRITE_CONTROL, 13, 2) - self._ref_command = RWBits(1, _WRITE_CONTROL, 12, 2) - self._gain_command = RWBits(1, _WRITE_CONTROL, 11, 2) + """ + Mode options + """ + self.normal_mode = const(0x00) + self.output_1k_impedance = const(0x01) + self.output_100k_impedance = const(0x02) + self.output_tristate = const(0x03) try: self.reset() - self.mode = NORMAL_MODE - self.enable_ref = True - self.gain = GAIN_1X + self._mode = self.normal_mode + self._internal_reference = True + self._gain = False + self._update_control_register() except OSError as error: raise OSError(f"Failed to initialize AD569x, {error}") from error @@ -104,54 +96,76 @@ def _send_command(self, command: int, data: int) -> None: high_byte = (data >> 8) & 0xFF low_byte = data & 0xFF buffer = bytearray([command, high_byte, low_byte]) - with self.i2c_device as i2c: - i2c.write(buffer) + try: + with self.i2c_device as i2c: + i2c.write(buffer) + except Exception: + with self.i2c_device as i2c: + i2c.write(buffer, end=False) except Exception as error: raise Exception(f"Error sending command: {error}") from error + def _update_control_register(self): + data = 0x0000 + data |= self._mode << 13 + data |= not self._internal_reference << 12 + data |= self._gain << 11 + self._send_command(_WRITE_CONTROL, data) + @property - def mode(self) -> int: + def mode(self): """ - Set the operating mode for the AD569x chip. + Operating mode for the AD569x chip. :param value: An int containing new operating mode. """ - return self._mode_command + return self._mode @mode.setter - def mode(self, value: int) -> None: - self._mode_command = value + def mode(self, new_mode): + if new_mode not in [0, 1, 2, 3]: + raise ValueError( + "Mode must be normal_mode, output_1k_impedance," + + "output_100k_impedance or output_tristate" + ) + self._mode = new_mode + self.reset() + self._update_control_register() @property - def ref_enabled(self) -> bool: + def internal_reference(self): """ - Enable the reference voltage for the AD569x chip. + Internal reference voltage for the AD569x chip. - :param value: A bool to enable the reference voltage. + :param value: A bool to enable the internal reference voltage. """ - return not bool(self._ref_command) + return self._internal_reference - @ref_enabled.setter - def ref_enabled(self, value: bool) -> None: - self._ref_command = value + @internal_reference.setter + def internal_reference(self, value): + self._internal_reference = value + self.reset() + self._update_control_register() @property - def gain(self) -> bool: + def gain(self): """ - Set the gain for the AD569x chip. + Gain for the AD569x chip. :param value: A bool to choose 1X or 2X gain. """ - return bool(self._gain_command) + return self._gain @gain.setter - def gain(self, value: bool) -> None: - self._gain_command = value + def gain(self, value): + self._gain = value + self.reset() + self._update_control_register() @property def value(self) -> int: """ - Write a 16-bit value to the input register and update the DAC register. + 16-bit value to the input register and update the DAC register. This property writes a 16-bit value to the input register and then updates the DAC register of the AD569x chip in a single operation. @@ -159,39 +173,15 @@ def value(self) -> int: return self.value @value.setter - def value(self, value: int) -> None: - self._send_command(_WRITE_DAC_AND_INPUT, value) - - @property - def dac(self) -> int: - """ - Write a 16-bit value to the input register. - - This function writes a 16-bit value to the input register of the AD569x chip. - """ - return self.dac - - @dac.setter - def dac(self, value: int) -> None: - # Use the internal _send_command function - self._send_command(_WRITE_INPUT, value) + def value(self, val: int) -> None: + self._send_command(_WRITE_DAC_AND_INPUT, val) - def update_dac(self) -> None: - """ - Update the DAC register from the input register. - - This function sends the UPDATE_DAC command to the AD569x chip to update - the DAC register based on the value stored in the input register. - """ - # Use the internal _send_command function with 0x0000 as data - self._send_command(_UPDATE_DAC, 0x0000) - - def reset(self) -> None: + def reset(self): """ Soft-reset the AD569x chip. - - This function writes 0x8000 to the control register of the AD569x chip - to perform a reset operation. Resets the DAC to zero-scale and - resets the input, DAC, and control registers to their default values. """ - self._reset_command = 1 + reset_command = 0x8000 + try: + self._send_command(_WRITE_CONTROL, reset_command) + except Exception as error: + raise Exception(f"Error during reset: {error}") from error diff --git a/docs/conf.py b/docs/conf.py index 9341b68..60970ba 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -32,7 +32,6 @@ "micropython", "busio", "adafruit_bus_device", - "adafruit_register", ] diff --git a/requirements.txt b/requirements.txt index 2c1fd4f..ae5e8e1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,4 +5,3 @@ Adafruit-Blinka adafruit-circuitpython-busdevice -adafruit-circuitpython-register From 4b0bc57999eae15d40356f4c1e3c3adad4ba9fa9 Mon Sep 17 00:00:00 2001 From: Liz Date: Tue, 14 Nov 2023 10:36:17 -0500 Subject: [PATCH 2/4] Update .pre-commit-config.yaml --- .pre-commit-config.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0e5fccc..70ade69 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,21 +4,21 @@ repos: - repo: https://github.com/python/black - rev: 22.3.0 + rev: 23.3.0 hooks: - id: black - repo: https://github.com/fsfe/reuse-tool - rev: v0.14.0 + rev: v1.1.2 hooks: - id: reuse - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.2.0 + rev: v4.4.0 hooks: - id: check-yaml - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/pycqa/pylint - rev: v2.15.5 + rev: v2.17.4 hooks: - id: pylint name: pylint (library code) From 72d2439c18504e7cabb9ec8ee0a2affe5bfca751 Mon Sep 17 00:00:00 2001 From: Liz Date: Tue, 14 Nov 2023 10:42:14 -0500 Subject: [PATCH 3/4] lint lint --- adafruit_ad569x.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/adafruit_ad569x.py b/adafruit_ad569x.py index 7ef0efc..080e142 100644 --- a/adafruit_ad569x.py +++ b/adafruit_ad569x.py @@ -50,6 +50,7 @@ _WRITE_CONTROL = const(0x40) +# pylint: disable=broad-exception-raised class Adafruit_AD569x: """Class which provides interface to AD569x Dac.""" @@ -99,7 +100,7 @@ def _send_command(self, command: int, data: int) -> None: try: with self.i2c_device as i2c: i2c.write(buffer) - except Exception: + except Exception: # pylint: disable=broad-exception-caught with self.i2c_device as i2c: i2c.write(buffer, end=False) except Exception as error: From 4a87cb4b779dc317ea6f26ec05564c5b49be0cf7 Mon Sep 17 00:00:00 2001 From: Liz Date: Tue, 14 Nov 2023 10:47:57 -0500 Subject: [PATCH 4/4] Update pyproject.toml --- pyproject.toml | 50 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f3c35ae..1e24763 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,48 @@ -# SPDX-FileCopyrightText: 2020 Diego Elio Pettenò +# SPDX-FileCopyrightText: 2022 Alec Delaney, written for Adafruit Industries +# SPDX-FileCopyrightText: Copyright (c) 2023 Liz Clark for Adafruit Industries # -# SPDX-License-Identifier: Unlicense +# SPDX-License-Identifier: MIT -[tool.black] -target-version = ['py35'] +[build-system] +requires = [ + "setuptools", + "wheel", + "setuptools-scm", +] + +[project] +name = "adafruit-circuitpython-ad569x" +description = "CircuitPython driver for the AD569x DAC" +version = "0.0.0+auto.0" +readme = "README.rst" +authors = [ + {name = "Adafruit Industries", email = "circuitpython@adafruit.com"} +] +urls = {Homepage = "https://github.com/adafruit/Adafruit_CircuitPython_AD569x"} +keywords = [ + "adafruit", + "blinka", + "circuitpython", + "micropython", + "ad569x", + "DAC", +] +license = {text = "MIT"} +classifiers = [ + "Intended Audience :: Developers", + "Topic :: Software Development :: Libraries", + "Topic :: Software Development :: Embedded Systems", + "Topic :: System :: Hardware", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", +] +dynamic = ["dependencies", "optional-dependencies"] + +[tool.setuptools] +# TODO: IF LIBRARY FILES ARE A PACKAGE FOLDER, +# CHANGE `py_modules = ['...']` TO `packages = ['...']` +py-modules = ["adafruit_ad569x"] + +[tool.setuptools.dynamic] +dependencies = {file = ["requirements.txt"]} +optional-dependencies = {optional = {file = ["optional_requirements.txt"]}}