├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── build.yml │ └── release.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .pylintrc ├── Adafruit_PureIO ├── __init__.py ├── smbus.py └── spi.py ├── CODE_OF_CONDUCT.md ├── LICENSE ├── LICENSES ├── CC-BY-4.0.txt ├── MIT.txt └── Unlicense.txt ├── README.rst ├── README.rst.license ├── docs ├── _static │ ├── favicon.ico │ └── favicon.ico.license ├── api.rst ├── api.rst.license ├── conf.py ├── index.rst └── index.rst.license ├── optional_requirements.txt ├── pyproject.toml ├── requirements.txt └── tests └── test_I2C.py /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | Thank you for opening an issue on an Adafruit Python library repository. To 8 | improve the speed of resolution please review the following guidelines and 9 | common troubleshooting steps below before creating the issue: 10 | 11 | - **Do not use GitHub issues for troubleshooting projects and issues.** Instead use 12 | the forums at http://forums.adafruit.com to ask questions and troubleshoot why 13 | something isn't working as expected. In many cases the problem is a common issue 14 | that you will more quickly receive help from the forum community. GitHub issues 15 | are meant for known defects in the code. If you don't know if there is a defect 16 | in the code then start with troubleshooting on the forum first. 17 | 18 | - **If following a tutorial or guide be sure you didn't miss a step.** Carefully 19 | check all of the steps and commands to run have been followed. Consult the 20 | forum if you're unsure or have questions about steps in a guide/tutorial. 21 | 22 | - **For Python/Raspberry Pi projects check these very common issues to ensure they don't apply**: 23 | 24 | - If you are receiving an **ImportError: No module named...** error then a 25 | library the code depends on is not installed. Check the tutorial/guide or 26 | README to ensure you have installed the necessary libraries. Usually the 27 | missing library can be installed with the `pip` tool, but check the tutorial/guide 28 | for the exact command. 29 | 30 | - **Be sure you are supplying adequate power to the board.** Check the specs of 31 | your board and power in an external power supply. In many cases just 32 | plugging a board into your computer is not enough to power it and other 33 | peripherals. 34 | 35 | - **Double check all soldering joints and connections.** Flakey connections 36 | cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints. 37 | 38 | If you're sure this issue is a defect in the code and checked the steps above 39 | please fill in the following fields to provide enough troubleshooting information. 40 | You may delete the guideline and text above to just leave the following details: 41 | 42 | - Platform/operating system (i.e. Raspberry Pi with Raspbian operating system, 43 | Windows 32-bit, Windows 64-bit, Mac OSX 64-bit, etc.): **INSERT PLATFORM/OPERATING 44 | SYSTEM HERE** 45 | 46 | - Python version (run `python -version` or `python3 -version`): **INSERT PYTHON 47 | VERSION HERE** 48 | 49 | - Error message you are receiving, including any Python exception traces: **INSERT 50 | ERROR MESAGE/EXCEPTION TRACES HERE*** 51 | 52 | - List the steps to reproduce the problem below (if possible attach code or commands 53 | to run): **LIST REPRO STEPS BELOW** 54 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | Thank you for creating a pull request to contribute to Adafruit's GitHub code! 8 | Before you open the request please review the following guidelines and tips to 9 | help it be more easily integrated: 10 | 11 | - **Describe the scope of your change--i.e. what the change does and what parts 12 | of the code were modified.** This will help us understand any risks of integrating 13 | the code. 14 | 15 | - **Describe any known limitations with your change.** For example if the change 16 | doesn't apply to a supported platform of the library please mention it. 17 | 18 | - **Please run any tests or examples that can exercise your modified code.** We 19 | strive to not break users of the code and running tests/examples helps with this 20 | process. 21 | 22 | Thank you again for contributing! We will try to test and integrate the change 23 | as soon as we can, but be aware we have many GitHub repositories to manage and 24 | can't immediately respond to every request. There is no need to bump or check in 25 | on a pull request (it will clutter the discussion of the request). 26 | 27 | Also don't be worried if the request is closed or not integrated--sometimes the 28 | priorities of Adafruit's GitHub code (education, ease of use) might not match the 29 | priorities of the pull request. Don't fret, the open source community thrives on 30 | forks and GitHub makes it easy to keep your changes in a forked repo. 31 | 32 | After reviewing the guidelines above you can delete this text from the pull request. 33 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2020 Melissa LeBlanc-Williams for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | name: Build CI 6 | 7 | on: [pull_request, push] 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Translate Repo Name For Build Tools filename_prefix 14 | id: repo-name 15 | run: echo "repo-name=Adafruit-PureIO" >> $GITHUB_OUTPUT 16 | - name: Set up Python 3.x 17 | uses: actions/setup-python@v4 18 | with: 19 | python-version: '3.x' 20 | - name: Versions 21 | run: | 22 | python3 --version 23 | - name: Checkout Current Repo 24 | uses: actions/checkout@v3 25 | with: 26 | submodules: true 27 | - name: Checkout tools repo 28 | uses: actions/checkout@v3 29 | with: 30 | repository: adafruit/actions-ci-circuitpython-libs 31 | path: actions-ci 32 | - name: Install dependencies 33 | # (e.g. - apt-get: gettext, etc; pip: circuitpython-build-tools, requirements.txt; etc.) 34 | run: | 35 | source actions-ci/install.sh 36 | - name: Pip install pre-commit & Sphinx 37 | run: | 38 | pip install --force-reinstall pre-commit Sphinx sphinx-rtd-theme 39 | - name: Library version 40 | run: git describe --dirty --always --tags 41 | - name: Run pre-commit 42 | run: pre-commit run --all-files 43 | - name: Build docs 44 | working-directory: docs 45 | run: sphinx-build -E -W -b html . _build/html 46 | - name: Check For pyproject.toml 47 | id: need-pypi 48 | run: | 49 | echo pyproject-toml=$( find . -wholename './pyproject.toml' ) >> $GITHUB_OUTPUT 50 | - name: Build Python package 51 | if: contains(steps.need-pypi.outputs.pyproject-toml, 'pyproject.toml') 52 | run: | 53 | pip install --upgrade build twine 54 | find -type f -not -path "./.*" -not -path "./docs*" \( -name "*.py" -o -name "*.toml" \) -exec sed -i -e "s/0.0.0+auto.0/1.2.3/" {} + 55 | python -m build 56 | twine check dist/* 57 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2020 Melissa LeBlanc-Williams for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | name: Release Actions 6 | 7 | on: 8 | release: 9 | types: [published] 10 | 11 | jobs: 12 | upload-pypi: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v3 16 | - name: Check For pyproject.toml 17 | id: need-pypi 18 | run: | 19 | echo pyproject-toml=$( find . -wholename './pyproject.toml' ) >> $GITHUB_OUTPUT 20 | - name: Set up Python 21 | if: contains(steps.need-pypi.outputs.pyproject-toml, 'pyproject.toml') 22 | uses: actions/setup-python@v4 23 | with: 24 | python-version: '3.x' 25 | - name: Install dependencies 26 | if: contains(steps.need-pypi.outputs.pyproject-toml, 'pyproject.toml') 27 | run: | 28 | python -m pip install --upgrade pip 29 | pip install --upgrade build twine 30 | - name: Build and publish 31 | if: contains(steps.need-pypi.outputs.pyproject-toml, 'pyproject.toml') 32 | env: 33 | TWINE_USERNAME: ${{ secrets.pypi_username }} 34 | TWINE_PASSWORD: ${{ secrets.pypi_password }} 35 | run: | 36 | find -type f -not -path "./.*" -not -path "./docs*" \( -name "*.py" -o -name "*.toml" \) -exec sed -i -e "s/0.0.0+auto.0/${{github.event.release.tag_name}}/" {} + 37 | python -m build 38 | twine upload dist/* 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2020 Melissa LeBlanc-Williams for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | setuptools-* 6 | # Byte-compiled / optimized / DLL files 7 | __pycache__/ 8 | *.py[cod] 9 | *$py.class 10 | 11 | # C extensions 12 | *.so 13 | 14 | # Distribution / packaging 15 | .Python 16 | env/ 17 | build/ 18 | develop-eggs/ 19 | dist/ 20 | downloads/ 21 | eggs/ 22 | .eggs/ 23 | lib/ 24 | lib64/ 25 | parts/ 26 | sdist/ 27 | var/ 28 | *.egg-info/ 29 | .installed.cfg 30 | *.egg 31 | 32 | # PyInstaller 33 | # Usually these files are written by a python script from a template 34 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 35 | *.manifest 36 | *.spec 37 | 38 | # Installer logs 39 | pip-log.txt 40 | pip-delete-this-directory.txt 41 | 42 | # Unit test / coverage reports 43 | htmlcov/ 44 | .tox/ 45 | .coverage 46 | .coverage.* 47 | .cache 48 | nosetests.xml 49 | coverage.xml 50 | *,cover 51 | .hypothesis/ 52 | 53 | # Translations 54 | *.mo 55 | *.pot 56 | 57 | # Django stuff: 58 | *.log 59 | 60 | # Sphinx documentation 61 | docs/_build/ 62 | 63 | # PyBuilder 64 | target/ 65 | 66 | #Ipython Notebook 67 | .ipynb_checkpoints 68 | 69 | .DS_STORE 70 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2020 Diego Elio Pettenò 2 | # 3 | # SPDX-License-Identifier: Unlicense 4 | 5 | repos: 6 | - repo: https://github.com/python/black 7 | rev: 23.3.0 8 | hooks: 9 | - id: black 10 | - repo: https://github.com/fsfe/reuse-tool 11 | rev: v1.1.2 12 | hooks: 13 | - id: reuse 14 | - repo: https://github.com/pre-commit/pre-commit-hooks 15 | rev: v4.4.0 16 | hooks: 17 | - id: check-yaml 18 | - id: end-of-file-fixer 19 | - id: trailing-whitespace 20 | - repo: https://github.com/pycqa/pylint 21 | rev: v2.17.4 22 | hooks: 23 | - id: pylint 24 | name: pylint (library code) 25 | types: [python] 26 | args: 27 | - --disable=consider-using-f-string 28 | exclude: "^(docs/|examples/|tests/|setup.py$)" 29 | - id: pylint 30 | name: pylint (example code) 31 | description: Run pylint rules on "examples/*.py" files 32 | types: [python] 33 | files: "^examples/" 34 | args: 35 | - --disable=missing-docstring,invalid-name,consider-using-f-string,duplicate-code 36 | - id: pylint 37 | name: pylint (test code) 38 | description: Run pylint rules on "tests/*.py" files 39 | types: [python] 40 | files: "^tests/" 41 | args: 42 | - --disable=missing-docstring,consider-using-f-string,duplicate-code 43 | -------------------------------------------------------------------------------- /.pylintrc: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2020 Melissa LeBlanc-Williams for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | [MAIN] 6 | 7 | # Analyse import fallback blocks. This can be used to support both Python 2 and 8 | # 3 compatible code, which means that the block might have code that exists 9 | # only in one or another interpreter, leading to false positives when analysed. 10 | analyse-fallback-blocks=no 11 | 12 | # Clear in-memory caches upon conclusion of linting. Useful if running pylint 13 | # in a server-like mode. 14 | clear-cache-post-run=no 15 | 16 | # Load and enable all available extensions. Use --list-extensions to see a list 17 | # all available extensions. 18 | #enable-all-extensions= 19 | 20 | # In error mode, messages with a category besides ERROR or FATAL are 21 | # suppressed, and no reports are done by default. Error mode is compatible with 22 | # disabling specific errors. 23 | #errors-only= 24 | 25 | # Always return a 0 (non-error) status code, even if lint errors are found. 26 | # This is primarily useful in continuous integration scripts. 27 | #exit-zero= 28 | 29 | # A comma-separated list of package or module names from where C extensions may 30 | # be loaded. Extensions are loading into the active Python interpreter and may 31 | # run arbitrary code. 32 | extension-pkg-allow-list= 33 | 34 | # A comma-separated list of package or module names from where C extensions may 35 | # be loaded. Extensions are loading into the active Python interpreter and may 36 | # run arbitrary code. (This is an alternative name to extension-pkg-allow-list 37 | # for backward compatibility.) 38 | extension-pkg-whitelist= 39 | 40 | # Return non-zero exit code if any of these messages/categories are detected, 41 | # even if score is above --fail-under value. Syntax same as enable. Messages 42 | # specified are enabled, while categories only check already-enabled messages. 43 | fail-on= 44 | 45 | # Specify a score threshold under which the program will exit with error. 46 | fail-under=10 47 | 48 | # Interpret the stdin as a python script, whose filename needs to be passed as 49 | # the module_or_package argument. 50 | #from-stdin= 51 | 52 | # Files or directories to be skipped. They should be base names, not paths. 53 | ignore=CVS 54 | 55 | # Add files or directories matching the regular expressions patterns to the 56 | # ignore-list. The regex matches against paths and can be in Posix or Windows 57 | # format. Because '\\' represents the directory delimiter on Windows systems, 58 | # it can't be used as an escape character. 59 | ignore-paths= 60 | 61 | # Files or directories matching the regular expression patterns are skipped. 62 | # The regex matches against base names, not paths. The default value ignores 63 | # Emacs file locks 64 | ignore-patterns=^\.# 65 | 66 | # List of module names for which member attributes should not be checked 67 | # (useful for modules/projects where namespaces are manipulated during runtime 68 | # and thus existing member attributes cannot be deduced by static analysis). It 69 | # supports qualified module names, as well as Unix pattern matching. 70 | ignored-modules= 71 | 72 | # Python code to execute, usually for sys.path manipulation such as 73 | # pygtk.require(). 74 | #init-hook= 75 | 76 | # Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the 77 | # number of processors available to use, and will cap the count on Windows to 78 | # avoid hangs. 79 | jobs=1 80 | 81 | # Control the amount of potential inferred values when inferring a single 82 | # object. This can help the performance when dealing with large functions or 83 | # complex, nested conditions. 84 | limit-inference-results=100 85 | 86 | # List of plugins (as comma separated values of python module names) to load, 87 | # usually to register additional checkers. 88 | load-plugins= 89 | 90 | # Pickle collected data for later comparisons. 91 | persistent=yes 92 | 93 | # Minimum Python version to use for version dependent checks. Will default to 94 | # the version used to run pylint. 95 | py-version=3.11 96 | 97 | # Discover python modules and packages in the file system subtree. 98 | recursive=no 99 | 100 | # Add paths to the list of the source roots. Supports globbing patterns. The 101 | # source root is an absolute path or a path relative to the current working 102 | # directory used to determine a package namespace for modules located under the 103 | # source root. 104 | source-roots= 105 | 106 | # When enabled, pylint would attempt to guess common misconfiguration and emit 107 | # user-friendly hints instead of false-positive error messages. 108 | suggestion-mode=yes 109 | 110 | # Allow loading of arbitrary C extensions. Extensions are imported into the 111 | # active Python interpreter and may run arbitrary code. 112 | unsafe-load-any-extension=no 113 | 114 | # In verbose mode, extra non-checker-related info will be displayed. 115 | #verbose= 116 | 117 | 118 | [BASIC] 119 | 120 | # Naming style matching correct argument names. 121 | argument-naming-style=snake_case 122 | 123 | # Regular expression matching correct argument names. Overrides argument- 124 | # naming-style. If left empty, argument names will be checked with the set 125 | # naming style. 126 | #argument-rgx= 127 | 128 | # Naming style matching correct attribute names. 129 | attr-naming-style=snake_case 130 | 131 | # Regular expression matching correct attribute names. Overrides attr-naming- 132 | # style. If left empty, attribute names will be checked with the set naming 133 | # style. 134 | #attr-rgx= 135 | 136 | # Bad variable names which should always be refused, separated by a comma. 137 | bad-names=foo, 138 | bar, 139 | baz, 140 | toto, 141 | tutu, 142 | tata 143 | 144 | # Bad variable names regexes, separated by a comma. If names match any regex, 145 | # they will always be refused 146 | bad-names-rgxs= 147 | 148 | # Naming style matching correct class attribute names. 149 | class-attribute-naming-style=any 150 | 151 | # Regular expression matching correct class attribute names. Overrides class- 152 | # attribute-naming-style. If left empty, class attribute names will be checked 153 | # with the set naming style. 154 | #class-attribute-rgx= 155 | 156 | # Naming style matching correct class constant names. 157 | class-const-naming-style=UPPER_CASE 158 | 159 | # Regular expression matching correct class constant names. Overrides class- 160 | # const-naming-style. If left empty, class constant names will be checked with 161 | # the set naming style. 162 | #class-const-rgx= 163 | 164 | # Naming style matching correct class names. 165 | class-naming-style=PascalCase 166 | 167 | # Regular expression matching correct class names. Overrides class-naming- 168 | # style. If left empty, class names will be checked with the set naming style. 169 | #class-rgx= 170 | 171 | # Naming style matching correct constant names. 172 | const-naming-style=UPPER_CASE 173 | 174 | # Regular expression matching correct constant names. Overrides const-naming- 175 | # style. If left empty, constant names will be checked with the set naming 176 | # style. 177 | #const-rgx= 178 | 179 | # Minimum line length for functions/classes that require docstrings, shorter 180 | # ones are exempt. 181 | docstring-min-length=-1 182 | 183 | # Naming style matching correct function names. 184 | function-naming-style=snake_case 185 | 186 | # Regular expression matching correct function names. Overrides function- 187 | # naming-style. If left empty, function names will be checked with the set 188 | # naming style. 189 | #function-rgx= 190 | 191 | # Good variable names which should always be accepted, separated by a comma. 192 | good-names=i, 193 | j, 194 | k, 195 | ex, 196 | Run, 197 | _ 198 | 199 | # Good variable names regexes, separated by a comma. If names match any regex, 200 | # they will always be accepted 201 | good-names-rgxs= 202 | 203 | # Include a hint for the correct naming format with invalid-name. 204 | include-naming-hint=no 205 | 206 | # Naming style matching correct inline iteration names. 207 | inlinevar-naming-style=any 208 | 209 | # Regular expression matching correct inline iteration names. Overrides 210 | # inlinevar-naming-style. If left empty, inline iteration names will be checked 211 | # with the set naming style. 212 | #inlinevar-rgx= 213 | 214 | # Naming style matching correct method names. 215 | method-naming-style=snake_case 216 | 217 | # Regular expression matching correct method names. Overrides method-naming- 218 | # style. If left empty, method names will be checked with the set naming style. 219 | #method-rgx= 220 | 221 | # Naming style matching correct module names. 222 | module-naming-style=snake_case 223 | 224 | # Regular expression matching correct module names. Overrides module-naming- 225 | # style. If left empty, module names will be checked with the set naming style. 226 | #module-rgx= 227 | 228 | # Colon-delimited sets of names that determine each other's naming style when 229 | # the name regexes allow several styles. 230 | name-group= 231 | 232 | # Regular expression which should only match function or class names that do 233 | # not require a docstring. 234 | no-docstring-rgx=^_ 235 | 236 | # List of decorators that produce properties, such as abc.abstractproperty. Add 237 | # to this list to register other decorators that produce valid properties. 238 | # These decorators are taken in consideration only for invalid-name. 239 | property-classes=abc.abstractproperty 240 | 241 | # Regular expression matching correct type alias names. If left empty, type 242 | # alias names will be checked with the set naming style. 243 | #typealias-rgx= 244 | 245 | # Regular expression matching correct type variable names. If left empty, type 246 | # variable names will be checked with the set naming style. 247 | #typevar-rgx= 248 | 249 | # Naming style matching correct variable names. 250 | variable-naming-style=snake_case 251 | 252 | # Regular expression matching correct variable names. Overrides variable- 253 | # naming-style. If left empty, variable names will be checked with the set 254 | # naming style. 255 | #variable-rgx= 256 | 257 | 258 | [CLASSES] 259 | 260 | # Warn about protected attribute access inside special methods 261 | check-protected-access-in-special-methods=no 262 | 263 | # List of method names used to declare (i.e. assign) instance attributes. 264 | defining-attr-methods=__init__, 265 | __new__, 266 | setUp, 267 | asyncSetUp, 268 | __post_init__ 269 | 270 | # List of member names, which should be excluded from the protected access 271 | # warning. 272 | exclude-protected=_asdict,_fields,_replace,_source,_make,os._exit 273 | 274 | # List of valid names for the first argument in a class method. 275 | valid-classmethod-first-arg=cls 276 | 277 | # List of valid names for the first argument in a metaclass class method. 278 | valid-metaclass-classmethod-first-arg=mcs 279 | 280 | 281 | [DESIGN] 282 | 283 | # List of regular expressions of class ancestor names to ignore when counting 284 | # public methods (see R0903) 285 | exclude-too-few-public-methods= 286 | 287 | # List of qualified class names to ignore when counting class parents (see 288 | # R0901) 289 | ignored-parents= 290 | 291 | # Maximum number of arguments for function / method. 292 | max-args=5 293 | 294 | # Maximum number of attributes for a class (see R0902). 295 | max-attributes=7 296 | 297 | # Maximum number of boolean expressions in an if statement (see R0916). 298 | max-bool-expr=5 299 | 300 | # Maximum number of branch for function / method body. 301 | max-branches=12 302 | 303 | # Maximum number of locals for function / method body. 304 | max-locals=15 305 | 306 | # Maximum number of parents for a class (see R0901). 307 | max-parents=7 308 | 309 | # Maximum number of public methods for a class (see R0904). 310 | max-public-methods=20 311 | 312 | # Maximum number of return / yield for function / method body. 313 | max-returns=6 314 | 315 | # Maximum number of statements in function / method body. 316 | max-statements=50 317 | 318 | # Minimum number of public methods for a class (see R0903). 319 | min-public-methods=2 320 | 321 | 322 | [EXCEPTIONS] 323 | 324 | # Exceptions that will emit a warning when caught. 325 | overgeneral-exceptions=builtins.BaseException,builtins.Exception 326 | 327 | 328 | [FORMAT] 329 | 330 | # Expected format of line ending, e.g. empty (any line ending), LF or CRLF. 331 | expected-line-ending-format= 332 | 333 | # Regexp for a line that is allowed to be longer than the limit. 334 | ignore-long-lines=^\s*(# )??$ 335 | 336 | # Number of spaces of indent required inside a hanging or continued line. 337 | indent-after-paren=4 338 | 339 | # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 340 | # tab). 341 | indent-string=' ' 342 | 343 | # Maximum number of characters on a single line. 344 | max-line-length=100 345 | 346 | # Maximum number of lines in a module. 347 | max-module-lines=1000 348 | 349 | # Allow the body of a class to be on the same line as the declaration if body 350 | # contains single statement. 351 | single-line-class-stmt=no 352 | 353 | # Allow the body of an if to be on the same line as the test if there is no 354 | # else. 355 | single-line-if-stmt=no 356 | 357 | 358 | [IMPORTS] 359 | 360 | # List of modules that can be imported at any level, not just the top level 361 | # one. 362 | allow-any-import-level= 363 | 364 | # Allow explicit reexports by alias from a package __init__. 365 | allow-reexport-from-package=no 366 | 367 | # Allow wildcard imports from modules that define __all__. 368 | allow-wildcard-with-all=no 369 | 370 | # Deprecated modules which should not be used, separated by a comma. 371 | deprecated-modules= 372 | 373 | # Output a graph (.gv or any supported image format) of external dependencies 374 | # to the given file (report RP0402 must not be disabled). 375 | ext-import-graph= 376 | 377 | # Output a graph (.gv or any supported image format) of all (i.e. internal and 378 | # external) dependencies to the given file (report RP0402 must not be 379 | # disabled). 380 | import-graph= 381 | 382 | # Output a graph (.gv or any supported image format) of internal dependencies 383 | # to the given file (report RP0402 must not be disabled). 384 | int-import-graph= 385 | 386 | # Force import order to recognize a module as part of the standard 387 | # compatibility libraries. 388 | known-standard-library= 389 | 390 | # Force import order to recognize a module as part of a third party library. 391 | known-third-party=enchant 392 | 393 | # Couples of modules and preferred modules, separated by a comma. 394 | preferred-modules= 395 | 396 | 397 | [LOGGING] 398 | 399 | # The type of string formatting that logging methods do. `old` means using % 400 | # formatting, `new` is for `{}` formatting. 401 | logging-format-style=old 402 | 403 | # Logging modules to check that the string format arguments are in logging 404 | # function parameter format. 405 | logging-modules=logging 406 | 407 | 408 | [MESSAGES CONTROL] 409 | 410 | # Only show warnings with the listed confidence levels. Leave empty to show 411 | # all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE, 412 | # UNDEFINED. 413 | confidence=HIGH, 414 | CONTROL_FLOW, 415 | INFERENCE, 416 | INFERENCE_FAILURE, 417 | UNDEFINED 418 | 419 | # Disable the message, report, category or checker with the given id(s). You 420 | # can either give multiple identifiers separated by comma (,) or put this 421 | # option multiple times (only on the command line, not in the configuration 422 | # file where it should appear only once). You can also use "--disable=all" to 423 | # disable everything first and then re-enable specific checks. For example, if 424 | # you want to run only the similarities checker, you can use "--disable=all 425 | # --enable=similarities". If you want to run only the classes checker, but have 426 | # no Warning level messages displayed, use "--disable=all --enable=classes 427 | # --disable=W". 428 | disable=raw-checker-failed, 429 | bad-inline-option, 430 | locally-disabled, 431 | file-ignored, 432 | suppressed-message, 433 | useless-suppression, 434 | deprecated-pragma, 435 | use-symbolic-message-instead, 436 | invalid-name, 437 | import-error 438 | 439 | # Enable the message, report, category or checker with the given id(s). You can 440 | # either give multiple identifier separated by comma (,) or put this option 441 | # multiple time (only on the command line, not in the configuration file where 442 | # it should appear only once). See also the "--disable" option for examples. 443 | enable=c-extension-no-member 444 | 445 | 446 | [METHOD_ARGS] 447 | 448 | # List of qualified names (i.e., library.method) which require a timeout 449 | # parameter e.g. 'requests.api.get,requests.api.post' 450 | timeout-methods=requests.api.delete,requests.api.get,requests.api.head,requests.api.options,requests.api.patch,requests.api.post,requests.api.put,requests.api.request 451 | 452 | 453 | [MISCELLANEOUS] 454 | 455 | # List of note tags to take in consideration, separated by a comma. 456 | notes=FIXME, 457 | XXX, 458 | TODO 459 | 460 | # Regular expression of note tags to take in consideration. 461 | notes-rgx= 462 | 463 | 464 | [REFACTORING] 465 | 466 | # Maximum number of nested blocks for function / method body 467 | max-nested-blocks=5 468 | 469 | # Complete name of functions that never returns. When checking for 470 | # inconsistent-return-statements if a never returning function is called then 471 | # it will be considered as an explicit return statement and no message will be 472 | # printed. 473 | never-returning-functions=sys.exit,argparse.parse_error 474 | 475 | 476 | [REPORTS] 477 | 478 | # Python expression which should return a score less than or equal to 10. You 479 | # have access to the variables 'fatal', 'error', 'warning', 'refactor', 480 | # 'convention', and 'info' which contain the number of messages in each 481 | # category, as well as 'statement' which is the total number of statements 482 | # analyzed. This score is used by the global evaluation report (RP0004). 483 | evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)) 484 | 485 | # Template used to display messages. This is a python new-style format string 486 | # used to format the message information. See doc for all details. 487 | msg-template= 488 | 489 | # Set the output format. Available formats are text, parseable, colorized, json 490 | # and msvs (visual studio). You can also give a reporter class, e.g. 491 | # mypackage.mymodule.MyReporterClass. 492 | #output-format= 493 | 494 | # Tells whether to display a full report or only the messages. 495 | reports=no 496 | 497 | # Activate the evaluation score. 498 | score=yes 499 | 500 | 501 | [SIMILARITIES] 502 | 503 | # Comments are removed from the similarity computation 504 | ignore-comments=yes 505 | 506 | # Docstrings are removed from the similarity computation 507 | ignore-docstrings=yes 508 | 509 | # Imports are removed from the similarity computation 510 | ignore-imports=yes 511 | 512 | # Signatures are removed from the similarity computation 513 | ignore-signatures=yes 514 | 515 | # Minimum lines number of a similarity. 516 | min-similarity-lines=4 517 | 518 | 519 | [SPELLING] 520 | 521 | # Limits count of emitted suggestions for spelling mistakes. 522 | max-spelling-suggestions=4 523 | 524 | # Spelling dictionary name. No available dictionaries : You need to install 525 | # both the python package and the system dependency for enchant to work.. 526 | spelling-dict= 527 | 528 | # List of comma separated words that should be considered directives if they 529 | # appear at the beginning of a comment and should not be checked. 530 | spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy: 531 | 532 | # List of comma separated words that should not be checked. 533 | spelling-ignore-words= 534 | 535 | # A path to a file that contains the private dictionary; one word per line. 536 | spelling-private-dict-file= 537 | 538 | # Tells whether to store unknown words to the private dictionary (see the 539 | # --spelling-private-dict-file option) instead of raising a message. 540 | spelling-store-unknown-words=no 541 | 542 | 543 | [STRING] 544 | 545 | # This flag controls whether inconsistent-quotes generates a warning when the 546 | # character used as a quote delimiter is used inconsistently within a module. 547 | check-quote-consistency=no 548 | 549 | # This flag controls whether the implicit-str-concat should generate a warning 550 | # on implicit string concatenation in sequences defined over several lines. 551 | check-str-concat-over-line-jumps=no 552 | 553 | 554 | [TYPECHECK] 555 | 556 | # List of decorators that produce context managers, such as 557 | # contextlib.contextmanager. Add to this list to register other decorators that 558 | # produce valid context managers. 559 | contextmanager-decorators=contextlib.contextmanager 560 | 561 | # List of members which are set dynamically and missed by pylint inference 562 | # system, and so shouldn't trigger E1101 when accessed. Python regular 563 | # expressions are accepted. 564 | generated-members= 565 | 566 | # Tells whether to warn about missing members when the owner of the attribute 567 | # is inferred to be None. 568 | ignore-none=yes 569 | 570 | # This flag controls whether pylint should warn about no-member and similar 571 | # checks whenever an opaque object is returned when inferring. The inference 572 | # can return multiple potential results while evaluating a Python object, but 573 | # some branches might not be evaluated, which results in partial inference. In 574 | # that case, it might be useful to still emit no-member and other checks for 575 | # the rest of the inferred objects. 576 | ignore-on-opaque-inference=yes 577 | 578 | # List of symbolic message names to ignore for Mixin members. 579 | ignored-checks-for-mixins=no-member, 580 | not-async-context-manager, 581 | not-context-manager, 582 | attribute-defined-outside-init 583 | 584 | # List of class names for which member attributes should not be checked (useful 585 | # for classes with dynamically set attributes). This supports the use of 586 | # qualified names. 587 | ignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace 588 | 589 | # Show a hint with possible names when a member name was not found. The aspect 590 | # of finding the hint is based on edit distance. 591 | missing-member-hint=yes 592 | 593 | # The minimum edit distance a name should have in order to be considered a 594 | # similar match for a missing member name. 595 | missing-member-hint-distance=1 596 | 597 | # The total number of similar names that should be taken in consideration when 598 | # showing a hint for a missing member. 599 | missing-member-max-choices=1 600 | 601 | # Regex pattern to define which classes are considered mixins. 602 | mixin-class-rgx=.*[Mm]ixin 603 | 604 | # List of decorators that change the signature of a decorated function. 605 | signature-mutators= 606 | 607 | 608 | [VARIABLES] 609 | 610 | # List of additional names supposed to be defined in builtins. Remember that 611 | # you should avoid defining new builtins when possible. 612 | additional-builtins= 613 | 614 | # Tells whether unused global variables should be treated as a violation. 615 | allow-global-unused-variables=yes 616 | 617 | # List of names allowed to shadow builtins 618 | allowed-redefined-builtins= 619 | 620 | # List of strings which can identify a callback function by name. A callback 621 | # name must start or end with one of those strings. 622 | callbacks=cb_, 623 | _cb 624 | 625 | # A regular expression matching the name of dummy variables (i.e. expected to 626 | # not be used). 627 | dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ 628 | 629 | # Argument names that match this expression will be ignored. 630 | ignored-argument-names=_.*|^ignored_|^unused_ 631 | 632 | # Tells whether we should check for unused import in __init__ files. 633 | init-import=no 634 | 635 | # List of qualified module names which can have objects that can redefine 636 | # builtins. 637 | redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io 638 | -------------------------------------------------------------------------------- /Adafruit_PureIO/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2020 Melissa LeBlanc-Williams for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | -------------------------------------------------------------------------------- /Adafruit_PureIO/smbus.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2016 Tony DiCola for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | 6 | """ 7 | `Adafruit_PureIO.smbus` 8 | ================================================================================ 9 | 10 | Pure python (i.e. no native extensions) access to Linux IO I2C interface that mimics the 11 | Python SMBus API. 12 | 13 | * Author(s): Tony DiCola, Lady Ada, Melissa LeBlanc-Williams 14 | 15 | Implementation Notes 16 | -------------------- 17 | 18 | **Software and Dependencies:** 19 | 20 | * Linux and Python 3.5 or Higher 21 | 22 | """ 23 | 24 | from ctypes import c_uint8, c_uint16, c_uint32, cast, pointer, POINTER 25 | from ctypes import create_string_buffer, Structure 26 | from fcntl import ioctl 27 | import struct 28 | 29 | # pylint: disable=fixme 30 | 31 | # I2C C API constants (from linux kernel headers) 32 | I2C_M_TEN = 0x0010 # this is a ten bit chip address 33 | I2C_M_RD = 0x0001 # read data, from slave to master 34 | I2C_M_STOP = 0x8000 # if I2C_FUNC_PROTOCOL_MANGLING 35 | I2C_M_NOSTART = 0x4000 # if I2C_FUNC_NOSTART 36 | I2C_M_REV_DIR_ADDR = 0x2000 # if I2C_FUNC_PROTOCOL_MANGLING 37 | I2C_M_IGNORE_NAK = 0x1000 # if I2C_FUNC_PROTOCOL_MANGLING 38 | I2C_M_NO_RD_ACK = 0x0800 # if I2C_FUNC_PROTOCOL_MANGLING 39 | I2C_M_RECV_LEN = 0x0400 # length will be first received byte 40 | 41 | I2C_SLAVE = 0x0703 # Use this slave address 42 | I2C_SLAVE_FORCE = 0x0706 # Use this slave address, even if 43 | # is already in use by a driver! 44 | I2C_TENBIT = 0x0704 # 0 for 7 bit addrs, != 0 for 10 bit 45 | I2C_FUNCS = 0x0705 # Get the adapter functionality mask 46 | I2C_RDWR = 0x0707 # Combined R/W transfer (one STOP only) 47 | I2C_PEC = 0x0708 # != 0 to use PEC with SMBus 48 | I2C_SMBUS = 0x0720 # SMBus transfer 49 | 50 | 51 | # ctypes versions of I2C structs defined by kernel. 52 | # Tone down pylint for the Python classes that mirror C structs. 53 | # pylint: disable=invalid-name,too-few-public-methods 54 | class i2c_msg(Structure): 55 | """Linux i2c_msg struct.""" 56 | 57 | _fields_ = [ 58 | ("addr", c_uint16), 59 | ("flags", c_uint16), 60 | ("len", c_uint16), 61 | ("buf", POINTER(c_uint8)), 62 | ] 63 | 64 | 65 | class i2c_rdwr_ioctl_data(Structure): # pylint: disable=invalid-name 66 | """Linux i2c data struct.""" 67 | 68 | _fields_ = [("msgs", POINTER(i2c_msg)), ("nmsgs", c_uint32)] 69 | 70 | 71 | # pylint: enable=invalid-name,too-few-public-methods 72 | 73 | 74 | # pylint: disable=attribute-defined-outside-init 75 | def make_i2c_rdwr_data(messages): 76 | """Utility function to create and return an i2c_rdwr_ioctl_data structure 77 | populated with a list of specified I2C messages. The messages parameter 78 | should be a list of tuples which represent the individual I2C messages to 79 | send in this transaction. Tuples should contain 4 elements: address value, 80 | flags value, buffer length, ctypes c_uint8 pointer to buffer. 81 | """ 82 | # Create message array and populate with provided data. 83 | msg_data_type = i2c_msg * len(messages) 84 | msg_data = msg_data_type() 85 | for i, message in enumerate(messages): 86 | msg_data[i].addr = message[0] & 0x7F 87 | msg_data[i].flags = message[1] 88 | msg_data[i].len = message[2] 89 | msg_data[i].buf = message[3] 90 | # Now build the data structure. 91 | data = i2c_rdwr_ioctl_data() 92 | data.msgs = msg_data 93 | data.nmsgs = len(messages) 94 | return data 95 | 96 | 97 | # pylint: enable=attribute-defined-outside-init 98 | 99 | 100 | # Create an interface that mimics the Python SMBus API. 101 | class SMBus: 102 | """I2C interface that mimics the Python SMBus API but is implemented with 103 | pure Python calls to ioctl and direct /dev/i2c device access. 104 | """ 105 | 106 | def __init__(self, bus=None): 107 | """Create a new smbus instance. Bus is an optional parameter that 108 | specifies the I2C bus number to use, for example 1 would use device 109 | /dev/i2c-1. If bus is not specified then the open function should be 110 | called to open the bus. 111 | """ 112 | self._device = None 113 | if bus is not None: 114 | self.open(bus) 115 | 116 | def __del__(self): 117 | """Clean up any resources used by the SMBus instance.""" 118 | self.close() 119 | 120 | def __enter__(self): 121 | """Context manager enter function.""" 122 | # Just return this object so it can be used in a with statement, like 123 | # with SMBus(1) as bus: 124 | # # do stuff! 125 | return self 126 | 127 | def __exit__(self, exc_type, exc_val, exc_tb): 128 | """Context manager exit function, ensures resources are cleaned up.""" 129 | self.close() 130 | return False # Don't suppress exceptions. 131 | 132 | def open(self, bus): 133 | """Open the smbus interface on the specified bus.""" 134 | # Close the device if it's already open. 135 | if self._device is not None: 136 | self.close() 137 | # Try to open the file for the specified bus. Must turn off buffering 138 | # or else Python 3 fails (see: https://bugs.python.org/issue20074) 139 | # pylint: disable=consider-using-with 140 | self._device = open(f"/dev/i2c-{bus}", "r+b", buffering=0) 141 | # pylint: enable=consider-using-with 142 | # TODO: Catch IOError and throw a better error message that describes 143 | # what's wrong (i.e. I2C may not be enabled or the bus doesn't exist). 144 | 145 | def close(self): 146 | """Close the smbus connection. You cannot make any other function 147 | calls on the bus unless open is called!""" 148 | if self._device is not None: 149 | self._device.close() 150 | self._device = None 151 | 152 | def _select_device(self, addr): 153 | """Set the address of the device to communicate with on the I2C bus.""" 154 | ioctl(self._device.fileno(), I2C_SLAVE, addr & 0x7F) 155 | 156 | def read_byte(self, addr): 157 | """Read a single byte from the specified device.""" 158 | assert ( 159 | self._device is not None 160 | ), "Bus must be opened before operations are made against it!" 161 | self._select_device(addr) 162 | return ord(self._device.read(1)) 163 | 164 | def read_bytes(self, addr, number): 165 | """Read many bytes from the specified device.""" 166 | assert ( 167 | self._device is not None 168 | ), "Bus must be opened before operations are made against it!" 169 | self._select_device(addr) 170 | return self._device.read(number) 171 | 172 | def read_byte_data(self, addr, cmd): 173 | """Read a single byte from the specified cmd register of the device.""" 174 | assert ( 175 | self._device is not None 176 | ), "Bus must be opened before operations are made against it!" 177 | # Build ctypes values to marshall between ioctl and Python. 178 | reg = c_uint8(cmd) 179 | result = c_uint8() 180 | # Build ioctl request. 181 | request = make_i2c_rdwr_data( 182 | [ 183 | (addr, 0, 1, pointer(reg)), # Write cmd register. 184 | (addr, I2C_M_RD, 1, pointer(result)), # Read 1 byte as result. 185 | ] 186 | ) 187 | # Make ioctl call and return result data. 188 | ioctl(self._device.fileno(), I2C_RDWR, request) 189 | return result.value 190 | 191 | def read_word_data(self, addr, cmd): 192 | """Read a word (2 bytes) from the specified cmd register of the device. 193 | Note that this will interpret data using the endianness of the processor 194 | running Python (typically little endian)! 195 | """ 196 | assert ( 197 | self._device is not None 198 | ), "Bus must be opened before operations are made against it!" 199 | # Build ctypes values to marshall between ioctl and Python. 200 | reg = c_uint8(cmd) 201 | result = c_uint16() 202 | # Build ioctl request. 203 | request = make_i2c_rdwr_data( 204 | [ 205 | (addr, 0, 1, pointer(reg)), # Write cmd register. 206 | ( 207 | addr, 208 | I2C_M_RD, 209 | 2, 210 | cast(pointer(result), POINTER(c_uint8)), 211 | ), # Read word (2 bytes). 212 | ] 213 | ) 214 | # Make ioctl call and return result data. 215 | ioctl(self._device.fileno(), I2C_RDWR, request) 216 | return result.value 217 | 218 | def read_block_data(self, addr, cmd): 219 | """Perform a block read from the specified cmd register of the device. 220 | The amount of data read is determined by the first byte send back by 221 | the device. Data is returned as a bytearray. 222 | """ 223 | # TODO: Unfortunately this will require calling the low level I2C 224 | # access ioctl to trigger a proper read_block_data. The amount of data 225 | # returned isn't known until the device starts responding so an I2C_RDWR 226 | # ioctl won't work. 227 | raise NotImplementedError() 228 | 229 | def read_i2c_block_data(self, addr, cmd, length=32): 230 | """Perform a read from the specified cmd register of device. Length number 231 | of bytes (default of 32) will be read and returned as a bytearray. 232 | """ 233 | assert ( 234 | self._device is not None 235 | ), "Bus must be opened before operations are made against it!" 236 | # Build ctypes values to marshall between ioctl and Python. 237 | 238 | # convert register into bytearray 239 | if not isinstance(cmd, (bytes, bytearray)): 240 | reg = cmd # backup 241 | cmd = bytearray(1) 242 | cmd[0] = reg 243 | 244 | cmdstring = create_string_buffer(len(cmd)) 245 | for i, val in enumerate(cmd): 246 | cmdstring[i] = val 247 | 248 | result = create_string_buffer(length) 249 | 250 | # Build ioctl request. 251 | request = make_i2c_rdwr_data( 252 | [ 253 | ( 254 | addr, 255 | 0, 256 | len(cmd), 257 | cast(cmdstring, POINTER(c_uint8)), 258 | ), # Write cmd register. 259 | (addr, I2C_M_RD, length, cast(result, POINTER(c_uint8))), # Read data. 260 | ] 261 | ) 262 | 263 | # Make ioctl call and return result data. 264 | ioctl(self._device.fileno(), I2C_RDWR, request) 265 | return bytearray( 266 | result.raw 267 | ) # Use .raw instead of .value which will stop at a null byte! 268 | 269 | def write_quick(self, addr): 270 | """Write a single byte to the specified device.""" 271 | # What a strange function, from the python-smbus source this appears to 272 | # just write a single byte that initiates a write to the specified device 273 | # address (but writes no data!). The functionality is duplicated below 274 | # but the actual use case for this is unknown. 275 | assert ( 276 | self._device is not None 277 | ), "Bus must be opened before operations are made against it!" 278 | # Build ioctl request. 279 | request = make_i2c_rdwr_data( 280 | [ 281 | (addr, 0, 0, None), 282 | ] 283 | ) # Write with no data. 284 | # Make ioctl call and return result data. 285 | ioctl(self._device.fileno(), I2C_RDWR, request) 286 | 287 | def write_byte(self, addr, val): 288 | """Write a single byte to the specified device.""" 289 | assert ( 290 | self._device is not None 291 | ), "Bus must be opened before operations are made against it!" 292 | self._select_device(addr) 293 | data = bytearray(1) 294 | data[0] = val & 0xFF 295 | self._device.write(data) 296 | 297 | def write_bytes(self, addr, buf): 298 | """Write many bytes to the specified device. buf is a bytearray""" 299 | assert ( 300 | self._device is not None 301 | ), "Bus must be opened before operations are made against it!" 302 | self._select_device(addr) 303 | self._device.write(buf) 304 | 305 | def write_byte_data(self, addr, cmd, val): 306 | """Write a byte of data to the specified cmd register of the device.""" 307 | assert ( 308 | self._device is not None 309 | ), "Bus must be opened before operations are made against it!" 310 | # Construct a string of data to send with the command register and byte value. 311 | data = bytearray(2) 312 | data[0] = cmd & 0xFF 313 | data[1] = val & 0xFF 314 | # Send the data to the device. 315 | self._select_device(addr) 316 | self._device.write(data) 317 | 318 | def write_word_data(self, addr, cmd, val): 319 | """Write a word (2 bytes) of data to the specified cmd register of the 320 | device. Note that this will write the data in the endianness of the 321 | processor running Python (typically little endian)! 322 | """ 323 | assert ( 324 | self._device is not None 325 | ), "Bus must be opened before operations are made against it!" 326 | # Construct a string of data to send with the command register and word value. 327 | data = struct.pack("=BH", cmd & 0xFF, val & 0xFFFF) 328 | # Send the data to the device. 329 | self._select_device(addr) 330 | self._device.write(data) 331 | 332 | def write_block_data(self, addr, cmd, vals): 333 | """Write a block of data to the specified cmd register of the device. 334 | The amount of data to write should be the first byte inside the vals 335 | string/bytearray and that count of bytes of data to write should follow 336 | it. 337 | """ 338 | # Just use the I2C block data write to write the provided values and 339 | # their length as the first byte. 340 | data = bytearray(len(vals) + 1) 341 | data[0] = len(vals) & 0xFF 342 | data[1:] = vals[0:] 343 | self.write_i2c_block_data(addr, cmd, data) 344 | 345 | def write_i2c_block_data(self, addr, cmd, vals): 346 | """Write a buffer of data to the specified cmd register of the device.""" 347 | assert ( 348 | self._device is not None 349 | ), "Bus must be opened before operations are made against it!" 350 | # Construct a string of data to send, including room for the command register. 351 | data = bytearray(len(vals) + 1) 352 | data[0] = cmd & 0xFF # Command register at the start. 353 | data[1:] = vals[0:] # Copy in the block data (ugly but necessary to ensure 354 | # the entire write happens in one transaction). 355 | # Send the data to the device. 356 | self._select_device(addr) 357 | self._device.write(data) 358 | 359 | def process_call(self, addr, cmd, val): 360 | """Perform a smbus process call by writing a word (2 byte) value to 361 | the specified register of the device, and then reading a word of response 362 | data (which is returned). 363 | """ 364 | assert ( 365 | self._device is not None 366 | ), "Bus must be opened before operations are made against it!" 367 | # Build ctypes values to marshall between ioctl and Python. 368 | data = create_string_buffer(struct.pack("=BH", cmd, val)) 369 | result = c_uint16() 370 | # Build ioctl request. 371 | request = make_i2c_rdwr_data( 372 | [ 373 | (addr, 0, 3, cast(pointer(data), POINTER(c_uint8))), # Write data. 374 | ( 375 | addr, 376 | I2C_M_RD, 377 | 2, 378 | cast(pointer(result), POINTER(c_uint8)), 379 | ), # Read word (2 bytes). 380 | ] 381 | ) 382 | # Make ioctl call and return result data. 383 | ioctl(self._device.fileno(), I2C_RDWR, request) 384 | # Note the python-smbus code appears to have a rather serious bug and 385 | # does not return the result value! This is fixed below by returning it. 386 | return result.value 387 | -------------------------------------------------------------------------------- /Adafruit_PureIO/spi.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2020 Melissa LeBlanc-Williams for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | """ 6 | `Adafruit_PureIO.spi` 7 | ================================================================================ 8 | 9 | Pure python (i.e. no native extensions) access to Linux IO SPI interface that is 10 | similar to the SpiDev API. Based heavily on https://github.com/tomstokes/python-spi/. 11 | 12 | * Author(s): Tom Stokes, Melissa LeBlanc-Williams 13 | 14 | Implementation Notes 15 | -------------------- 16 | 17 | **Software and Dependencies:** 18 | 19 | * Linux and Python 3.5 or Higher 20 | 21 | """ 22 | 23 | # imports 24 | from ctypes import create_string_buffer, string_at, addressof 25 | from fcntl import ioctl 26 | import struct 27 | import platform 28 | import os.path 29 | from os import environ 30 | import array 31 | 32 | __version__ = "0.0.0+auto.0" 33 | __repo__ = "https://github.com/adafruit/Adafruit_Python_PureIO.git" 34 | 35 | # SPI C API constants (from linux kernel headers) 36 | SPI_CPHA = 0x01 37 | SPI_CPOL = 0x02 38 | SPI_CS_HIGH = 0x04 39 | SPI_LSB_FIRST = 0x08 40 | SPI_THREE_WIRE = 0x10 41 | SPI_LOOP = 0x20 42 | SPI_NO_CS = 0x40 43 | SPI_READY = 0x80 44 | SPI_TX_DUAL = 0x100 45 | SPI_TX_QUAD = 0x200 46 | SPI_RX_DUAL = 0x400 47 | SPI_RX_QUAD = 0x800 48 | 49 | SPI_MODE_0 = 0 50 | SPI_MODE_1 = SPI_CPHA 51 | SPI_MODE_2 = SPI_CPOL 52 | SPI_MODE_3 = SPI_CPHA | SPI_CPOL 53 | 54 | SPI_DEFAULT_CHUNK_SIZE = 4096 55 | 56 | 57 | def _ioc_encode(direction, number, structure): 58 | """ 59 | ioctl command encoding helper function 60 | Calculates the appropriate spidev ioctl op argument given the direction, 61 | command number, and argument structure in python's struct.pack format. 62 | Returns a tuple of the calculated op and the struct.pack format 63 | See Linux kernel source file /include/uapi/asm/ioctl.h 64 | """ 65 | ioc_magic = ord("k") 66 | ioc_nrbits = 8 67 | ioc_typebits = 8 68 | if platform.machine() == "mips": 69 | ioc_sizebits = 13 70 | else: 71 | ioc_sizebits = 14 72 | 73 | ioc_nrshift = 0 74 | ioc_typeshift = ioc_nrshift + ioc_nrbits 75 | ioc_sizeshift = ioc_typeshift + ioc_typebits 76 | ioc_dirshift = ioc_sizeshift + ioc_sizebits 77 | 78 | size = struct.calcsize(structure) 79 | 80 | operation = ( 81 | (direction << ioc_dirshift) 82 | | (ioc_magic << ioc_typeshift) 83 | | (number << ioc_nrshift) 84 | | (size << ioc_sizeshift) 85 | ) 86 | 87 | return direction, operation, structure 88 | 89 | 90 | # pylint: disable=too-many-instance-attributes, too-many-branches 91 | class SPI: 92 | """ 93 | This class is similar to SpiDev, but instead of opening and closing 94 | for each call, it is set up on initialization making it fast. 95 | """ 96 | 97 | _IOC_TRANSFER_FORMAT = "QQIIHBBBBH" 98 | 99 | if platform.machine() == "mips": 100 | # Direction is 3 bits 101 | _IOC_READ = 2 102 | _IOC_WRITE = 4 103 | else: 104 | # Direction is 2 bits 105 | _IOC_WRITE = 1 106 | _IOC_READ = 2 107 | 108 | # _IOC_MESSAGE is a special case, so we ony need the ioctl operation 109 | _IOC_MESSAGE = _ioc_encode(_IOC_WRITE, 0, _IOC_TRANSFER_FORMAT)[1] 110 | 111 | _IOC_RD_MODE = _ioc_encode(_IOC_READ, 1, "B") 112 | _IOC_WR_MODE = _ioc_encode(_IOC_WRITE, 1, "B") 113 | 114 | _IOC_RD_LSB_FIRST = _ioc_encode(_IOC_READ, 2, "B") 115 | _IOC_WR_LSB_FIRST = _ioc_encode(_IOC_WRITE, 2, "B") 116 | 117 | _IOC_RD_BITS_PER_WORD = _ioc_encode(_IOC_READ, 3, "B") 118 | _IOC_WR_BITS_PER_WORD = _ioc_encode(_IOC_WRITE, 3, "B") 119 | 120 | _IOC_RD_MAX_SPEED_HZ = _ioc_encode(_IOC_READ, 4, "I") 121 | _IOC_WR_MAX_SPEED_HZ = _ioc_encode(_IOC_WRITE, 4, "I") 122 | 123 | _IOC_RD_MODE32 = _ioc_encode(_IOC_READ, 5, "I") 124 | _IOC_WR_MODE32 = _ioc_encode(_IOC_WRITE, 5, "I") 125 | # pylint: disable=too-many-arguments 126 | 127 | def __init__( 128 | self, 129 | device, 130 | max_speed_hz=None, 131 | bits_per_word=None, 132 | phase=None, 133 | polarity=None, 134 | cs_high=None, 135 | lsb_first=None, 136 | three_wire=None, 137 | loop=None, 138 | no_cs=None, 139 | ready=None, 140 | ): 141 | """ 142 | Create spidev interface object. 143 | """ 144 | if isinstance(device, tuple): 145 | (bus, dev) = device 146 | device = f"/dev/spidev{bus:d}.{dev:d}" 147 | 148 | if not os.path.exists(device): 149 | raise IOError(f"{device} does not exist") 150 | 151 | self.handle = os.open(device, os.O_RDWR) 152 | 153 | self.chunk_size = SPI_DEFAULT_CHUNK_SIZE 154 | if environ.get("SPI_BUFSIZE") is not None: 155 | try: 156 | self.chunk_size = int(os.environ.get("SPI_BUFSIZE")) 157 | except ValueError: 158 | self.chunk_size = SPI_DEFAULT_CHUNK_SIZE 159 | 160 | if max_speed_hz is not None: 161 | self.max_speed_hz = max_speed_hz 162 | 163 | if bits_per_word is not None: 164 | self.bits_per_word = bits_per_word 165 | 166 | if phase is not None: 167 | self.phase = phase 168 | 169 | if polarity is not None: 170 | self.polarity = polarity 171 | 172 | if cs_high is not None: 173 | self.cs_high = cs_high 174 | 175 | if lsb_first is not None: 176 | self.lsb_first = lsb_first 177 | 178 | if three_wire is not None: 179 | self.three_wire = three_wire 180 | 181 | if loop is not None: 182 | self.loop = loop 183 | 184 | if no_cs is not None: 185 | self.no_cs = no_cs 186 | 187 | if ready is not None: 188 | self.ready = ready 189 | 190 | # pylint: enable=too-many-arguments 191 | 192 | def _ioctl(self, ioctl_data, data=None): 193 | """ 194 | ioctl helper function. 195 | 196 | Performs an ioctl on self.handle. If the ioctl is an SPI read type 197 | ioctl, returns the result value. 198 | """ 199 | (direction, ioctl_bytes, structure) = ioctl_data 200 | if direction == SPI._IOC_READ: 201 | arg = array.array(structure, [0]) 202 | ioctl(self.handle, ioctl_bytes, arg, True) 203 | return arg[0] 204 | 205 | arg = struct.pack("=" + structure, data) 206 | ioctl(self.handle, ioctl_bytes, arg) 207 | return None 208 | 209 | def _get_mode_field(self, field): 210 | """Helper function to get specific spidev mode bits""" 211 | return bool(self._ioctl(SPI._IOC_RD_MODE) & field) 212 | 213 | def _set_mode_field(self, field, value): 214 | """Helper function to set a spidev mode bit""" 215 | mode = self._ioctl(SPI._IOC_RD_MODE) 216 | if value: 217 | mode |= field 218 | else: 219 | mode &= ~field 220 | self._ioctl(SPI._IOC_WR_MODE, mode) 221 | 222 | @property 223 | def phase(self): 224 | """SPI clock phase bit""" 225 | return self._get_mode_field(SPI_CPHA) 226 | 227 | @phase.setter 228 | def phase(self, phase): 229 | self._set_mode_field(SPI_CPHA, phase) 230 | 231 | @property 232 | def polarity(self): 233 | """SPI polarity bit""" 234 | return self._get_mode_field(SPI_CPOL) 235 | 236 | @polarity.setter 237 | def polarity(self, polarity): 238 | self._set_mode_field(SPI_CPOL, polarity) 239 | 240 | @property 241 | def cs_high(self): 242 | """SPI chip select active level""" 243 | return self._get_mode_field(SPI_CS_HIGH) 244 | 245 | @cs_high.setter 246 | def cs_high(self, cs_high): 247 | self._set_mode_field(SPI_CS_HIGH, cs_high) 248 | 249 | @property 250 | def lsb_first(self): 251 | """Bit order of SPI word transfers""" 252 | return self._get_mode_field(SPI_LSB_FIRST) 253 | 254 | @lsb_first.setter 255 | def lsb_first(self, lsb_first): 256 | self._set_mode_field(SPI_LSB_FIRST, lsb_first) 257 | 258 | @property 259 | def three_wire(self): 260 | """SPI 3-wire mode""" 261 | return self._get_mode_field(SPI_THREE_WIRE) 262 | 263 | @three_wire.setter 264 | def three_wire(self, three_wire): 265 | self._set_mode_field(SPI_THREE_WIRE, three_wire) 266 | 267 | @property 268 | def loop(self): 269 | """SPI loopback mode""" 270 | return self._get_mode_field(SPI_LOOP) 271 | 272 | @loop.setter 273 | def loop(self, loop): 274 | self._set_mode_field(SPI_LOOP, loop) 275 | 276 | @property 277 | def no_cs(self): 278 | """No chipselect. Single device on bus.""" 279 | return self._get_mode_field(SPI_NO_CS) 280 | 281 | @no_cs.setter 282 | def no_cs(self, no_cs): 283 | self._set_mode_field(SPI_NO_CS, no_cs) 284 | 285 | @property 286 | def ready(self): 287 | """Slave pulls low to pause""" 288 | return self._get_mode_field(SPI_READY) 289 | 290 | @ready.setter 291 | def ready(self, ready): 292 | self._set_mode_field(SPI_READY, ready) 293 | 294 | @property 295 | def max_speed_hz(self): 296 | """Maximum SPI transfer speed in Hz. 297 | 298 | Note that the controller cannot necessarily assign the requested 299 | speed. 300 | """ 301 | return self._ioctl(SPI._IOC_RD_MAX_SPEED_HZ) 302 | 303 | @max_speed_hz.setter 304 | def max_speed_hz(self, max_speed_hz): 305 | self._ioctl(SPI._IOC_WR_MAX_SPEED_HZ, max_speed_hz) 306 | 307 | @property 308 | def bits_per_word(self): 309 | """Number of bits per word of SPI transfer. 310 | 311 | A value of 0 is equivalent to 8 bits per word 312 | """ 313 | return self._ioctl(SPI._IOC_RD_BITS_PER_WORD) 314 | 315 | @bits_per_word.setter 316 | def bits_per_word(self, bits_per_word): 317 | self._ioctl(SPI._IOC_WR_BITS_PER_WORD, bits_per_word) 318 | 319 | @property 320 | def mode(self): 321 | """Mode that SPI is currently running in""" 322 | return self._ioctl(SPI._IOC_RD_MODE) 323 | 324 | @mode.setter 325 | def mode(self, mode): 326 | self._ioctl(SPI._IOC_WR_MODE, mode) 327 | 328 | def writebytes(self, data, max_speed_hz=0, bits_per_word=0, delay=0): 329 | """Perform half-duplex SPI write.""" 330 | data = array.array("B", data).tobytes() 331 | # length = len(data) 332 | chunks = [ 333 | data[i : i + self.chunk_size] for i in range(0, len(data), self.chunk_size) 334 | ] 335 | for chunk in chunks: 336 | length = len(chunk) 337 | transmit_buffer = create_string_buffer(chunk) 338 | spi_ioc_transfer = struct.pack( 339 | SPI._IOC_TRANSFER_FORMAT, 340 | addressof(transmit_buffer), 341 | 0, 342 | length, 343 | max_speed_hz, 344 | delay, 345 | bits_per_word, 346 | 0, 347 | 0, 348 | 0, 349 | 0, 350 | ) 351 | try: 352 | ioctl(self.handle, SPI._IOC_MESSAGE, spi_ioc_transfer) 353 | except TimeoutError as err: 354 | raise Exception( # pylint: disable=broad-exception-raised 355 | "ioctl timeout. Please try a different SPI frequency or less data." 356 | ) from err 357 | 358 | def readbytes(self, length, max_speed_hz=0, bits_per_word=0, delay=0): 359 | """Perform half-duplex SPI read as a binary string""" 360 | receive_buffer = create_string_buffer(length) 361 | spi_ioc_transfer = struct.pack( 362 | SPI._IOC_TRANSFER_FORMAT, 363 | 0, 364 | addressof(receive_buffer), 365 | length, 366 | max_speed_hz, 367 | delay, 368 | bits_per_word, 369 | 0, 370 | 0, 371 | 0, 372 | 0, 373 | ) 374 | ioctl(self.handle, SPI._IOC_MESSAGE, spi_ioc_transfer) 375 | return string_at(receive_buffer, length) 376 | 377 | def transfer(self, data, max_speed_hz=0, bits_per_word=0, delay=0): 378 | """Perform full-duplex SPI transfer""" 379 | data = array.array("B", data).tobytes() 380 | receive_data = [] 381 | 382 | chunks = [ 383 | data[i : i + self.chunk_size] for i in range(0, len(data), self.chunk_size) 384 | ] 385 | for chunk in chunks: 386 | length = len(chunk) 387 | receive_buffer = create_string_buffer(length) 388 | transmit_buffer = create_string_buffer(chunk) 389 | spi_ioc_transfer = struct.pack( 390 | SPI._IOC_TRANSFER_FORMAT, 391 | addressof(transmit_buffer), 392 | addressof(receive_buffer), 393 | length, 394 | max_speed_hz, 395 | delay, 396 | bits_per_word, 397 | 0, 398 | 0, 399 | 0, 400 | 0, 401 | ) 402 | ioctl(self.handle, SPI._IOC_MESSAGE, spi_ioc_transfer) 403 | receive_data += string_at(receive_buffer, length) 404 | return receive_data 405 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | # Adafruit Community Code of Conduct 9 | 10 | ## Our Pledge 11 | 12 | In the interest of fostering an open and welcoming environment, we as 13 | contributors and leaders pledge to making participation in our project and 14 | our community a harassment-free experience for everyone, regardless of age, body 15 | size, disability, ethnicity, gender identity and expression, level or type of 16 | experience, education, socio-economic status, nationality, personal appearance, 17 | race, religion, or sexual identity and orientation. 18 | 19 | ## Our Standards 20 | 21 | We are committed to providing a friendly, safe and welcoming environment for 22 | all. 23 | 24 | Examples of behavior that contributes to creating a positive environment 25 | include: 26 | 27 | * Be kind and courteous to others 28 | * Using welcoming and inclusive language 29 | * Being respectful of differing viewpoints and experiences 30 | * Collaborating with other community members 31 | * Gracefully accepting constructive criticism 32 | * Focusing on what is best for the community 33 | * Showing empathy towards other community members 34 | 35 | Examples of unacceptable behavior by participants include: 36 | 37 | * The use of sexualized language or imagery and sexual attention or advances 38 | * The use of inappropriate images, including in a community member's avatar 39 | * The use of inappropriate language, including in a community member's nickname 40 | * Any spamming, flaming, baiting or other attention-stealing behavior 41 | * Excessive or unwelcome helping; answering outside the scope of the question 42 | asked 43 | * Trolling, insulting/derogatory comments, and personal or political attacks 44 | * Promoting or spreading disinformation, lies, or conspiracy theories against 45 | a person, group, organisation, project, or community 46 | * Public or private harassment 47 | * Publishing others' private information, such as a physical or electronic 48 | address, without explicit permission 49 | * Other conduct which could reasonably be considered inappropriate 50 | 51 | The goal of the standards and moderation guidelines outlined here is to build 52 | and maintain a respectful community. We ask that you don’t just aim to be 53 | "technically unimpeachable", but rather try to be your best self. 54 | 55 | We value many things beyond technical expertise, including collaboration and 56 | supporting others within our community. Providing a positive experience for 57 | other community members can have a much more significant impact than simply 58 | providing the correct answer. 59 | 60 | ## Our Responsibilities 61 | 62 | Project leaders are responsible for clarifying the standards of acceptable 63 | behavior and are expected to take appropriate and fair corrective action in 64 | response to any instances of unacceptable behavior. 65 | 66 | Project leaders have the right and responsibility to remove, edit, or 67 | reject messages, comments, commits, code, issues, and other contributions 68 | that are not aligned to this Code of Conduct, or to ban temporarily or 69 | permanently any community member for other behaviors that they deem 70 | inappropriate, threatening, offensive, or harmful. 71 | 72 | ## Moderation 73 | 74 | Instances of behaviors that violate the Adafruit Community Code of Conduct 75 | may be reported by any member of the community. Community members are 76 | encouraged to report these situations, including situations they witness 77 | involving other community members. 78 | 79 | You may report in the following ways: 80 | 81 | In any situation, you may send an email to . 82 | 83 | On the Adafruit Discord, you may send an open message from any channel 84 | to all Community Moderators by tagging @community moderators. You may 85 | also send an open message from any channel, or a direct message to 86 | @kattni#1507, @tannewt#4653, @Dan Halbert#1614, @cater#2442, 87 | @sommersoft#0222, @Mr. Certainly#0472 or @Andon#8175. 88 | 89 | Email and direct message reports will be kept confidential. 90 | 91 | In situations on Discord where the issue is particularly egregious, possibly 92 | illegal, requires immediate action, or violates the Discord terms of service, 93 | you should also report the message directly to Discord. 94 | 95 | These are the steps for upholding our community’s standards of conduct. 96 | 97 | 1. Any member of the community may report any situation that violates the 98 | Adafruit Community Code of Conduct. All reports will be reviewed and 99 | investigated. 100 | 2. If the behavior is an egregious violation, the community member who 101 | committed the violation may be banned immediately, without warning. 102 | 3. Otherwise, moderators will first respond to such behavior with a warning. 103 | 4. Moderators follow a soft "three strikes" policy - the community member may 104 | be given another chance, if they are receptive to the warning and change their 105 | behavior. 106 | 5. If the community member is unreceptive or unreasonable when warned by a 107 | moderator, or the warning goes unheeded, they may be banned for a first or 108 | second offense. Repeated offenses will result in the community member being 109 | banned. 110 | 111 | ## Scope 112 | 113 | This Code of Conduct and the enforcement policies listed above apply to all 114 | Adafruit Community venues. This includes but is not limited to any community 115 | spaces (both public and private), the entire Adafruit Discord server, and 116 | Adafruit GitHub repositories. Examples of Adafruit Community spaces include 117 | but are not limited to meet-ups, audio chats on the Adafruit Discord, or 118 | interaction at a conference. 119 | 120 | This Code of Conduct applies both within project spaces and in public spaces 121 | when an individual is representing the project or its community. As a community 122 | member, you are representing our community, and are expected to behave 123 | accordingly. 124 | 125 | ## Attribution 126 | 127 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 128 | version 1.4, available at 129 | , 130 | and the [Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html). 131 | 132 | For other projects adopting the Adafruit Community Code of 133 | Conduct, please contact the maintainers of those projects for enforcement. 134 | If you wish to use this code of conduct for your own project, consider 135 | explicitly mentioning your moderation policy or making a copy with your 136 | own moderation policy so as to avoid confusion. 137 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 Melissa LeBlanc-Williams 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSES/CC-BY-4.0.txt: -------------------------------------------------------------------------------- 1 | Creative Commons Attribution 4.0 International Creative Commons Corporation 2 | ("Creative Commons") is not a law firm and does not provide legal services 3 | or legal advice. Distribution of Creative Commons public licenses does not 4 | create a lawyer-client or other relationship. Creative Commons makes its licenses 5 | and related information available on an "as-is" basis. Creative Commons gives 6 | no warranties regarding its licenses, any material licensed under their terms 7 | and conditions, or any related information. Creative Commons disclaims all 8 | liability for damages resulting from their use to the fullest extent possible. 9 | 10 | Using Creative Commons Public Licenses 11 | 12 | Creative Commons public licenses provide a standard set of terms and conditions 13 | that creators and other rights holders may use to share original works of 14 | authorship and other material subject to copyright and certain other rights 15 | specified in the public license below. The following considerations are for 16 | informational purposes only, are not exhaustive, and do not form part of our 17 | licenses. 18 | 19 | Considerations for licensors: Our public licenses are intended for use by 20 | those authorized to give the public permission to use material in ways otherwise 21 | restricted by copyright and certain other rights. Our licenses are irrevocable. 22 | Licensors should read and understand the terms and conditions of the license 23 | they choose before applying it. Licensors should also secure all rights necessary 24 | before applying our licenses so that the public can reuse the material as 25 | expected. Licensors should clearly mark any material not subject to the license. 26 | This includes other CC-licensed material, or material used under an exception 27 | or limitation to copyright. More considerations for licensors : wiki.creativecommons.org/Considerations_for_licensors 28 | 29 | Considerations for the public: By using one of our public licenses, a licensor 30 | grants the public permission to use the licensed material under specified 31 | terms and conditions. If the licensor's permission is not necessary for any 32 | reason–for example, because of any applicable exception or limitation to copyright–then 33 | that use is not regulated by the license. Our licenses grant only permissions 34 | under copyright and certain other rights that a licensor has authority to 35 | grant. Use of the licensed material may still be restricted for other reasons, 36 | including because others have copyright or other rights in the material. A 37 | licensor may make special requests, such as asking that all changes be marked 38 | or described. Although not required by our licenses, you are encouraged to 39 | respect those requests where reasonable. More considerations for the public 40 | : wiki.creativecommons.org/Considerations_for_licensees Creative Commons Attribution 41 | 4.0 International Public License 42 | 43 | By exercising the Licensed Rights (defined below), You accept and agree to 44 | be bound by the terms and conditions of this Creative Commons Attribution 45 | 4.0 International Public License ("Public License"). To the extent this Public 46 | License may be interpreted as a contract, You are granted the Licensed Rights 47 | in consideration of Your acceptance of these terms and conditions, and the 48 | Licensor grants You such rights in consideration of benefits the Licensor 49 | receives from making the Licensed Material available under these terms and 50 | conditions. 51 | 52 | Section 1 – Definitions. 53 | 54 | a. Adapted Material means material subject to Copyright and Similar Rights 55 | that is derived from or based upon the Licensed Material and in which the 56 | Licensed Material is translated, altered, arranged, transformed, or otherwise 57 | modified in a manner requiring permission under the Copyright and Similar 58 | Rights held by the Licensor. For purposes of this Public License, where the 59 | Licensed Material is a musical work, performance, or sound recording, Adapted 60 | Material is always produced where the Licensed Material is synched in timed 61 | relation with a moving image. 62 | 63 | b. Adapter's License means the license You apply to Your Copyright and Similar 64 | Rights in Your contributions to Adapted Material in accordance with the terms 65 | and conditions of this Public License. 66 | 67 | c. Copyright and Similar Rights means copyright and/or similar rights closely 68 | related to copyright including, without limitation, performance, broadcast, 69 | sound recording, and Sui Generis Database Rights, without regard to how the 70 | rights are labeled or categorized. For purposes of this Public License, the 71 | rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. 72 | 73 | d. Effective Technological Measures means those measures that, in the absence 74 | of proper authority, may not be circumvented under laws fulfilling obligations 75 | under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, 76 | and/or similar international agreements. 77 | 78 | e. Exceptions and Limitations means fair use, fair dealing, and/or any other 79 | exception or limitation to Copyright and Similar Rights that applies to Your 80 | use of the Licensed Material. 81 | 82 | f. Licensed Material means the artistic or literary work, database, or other 83 | material to which the Licensor applied this Public License. 84 | 85 | g. Licensed Rights means the rights granted to You subject to the terms and 86 | conditions of this Public License, which are limited to all Copyright and 87 | Similar Rights that apply to Your use of the Licensed Material and that the 88 | Licensor has authority to license. 89 | 90 | h. Licensor means the individual(s) or entity(ies) granting rights under this 91 | Public License. 92 | 93 | i. Share means to provide material to the public by any means or process that 94 | requires permission under the Licensed Rights, such as reproduction, public 95 | display, public performance, distribution, dissemination, communication, or 96 | importation, and to make material available to the public including in ways 97 | that members of the public may access the material from a place and at a time 98 | individually chosen by them. 99 | 100 | j. Sui Generis Database Rights means rights other than copyright resulting 101 | from Directive 96/9/EC of the European Parliament and of the Council of 11 102 | March 1996 on the legal protection of databases, as amended and/or succeeded, 103 | as well as other essentially equivalent rights anywhere in the world. 104 | 105 | k. You means the individual or entity exercising the Licensed Rights under 106 | this Public License. Your has a corresponding meaning. 107 | 108 | Section 2 – Scope. 109 | 110 | a. License grant. 111 | 112 | 1. Subject to the terms and conditions of this Public License, the Licensor 113 | hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, 114 | irrevocable license to exercise the Licensed Rights in the Licensed Material 115 | to: 116 | 117 | A. reproduce and Share the Licensed Material, in whole or in part; and 118 | 119 | B. produce, reproduce, and Share Adapted Material. 120 | 121 | 2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions 122 | and Limitations apply to Your use, this Public License does not apply, and 123 | You do not need to comply with its terms and conditions. 124 | 125 | 3. Term. The term of this Public License is specified in Section 6(a). 126 | 127 | 4. Media and formats; technical modifications allowed. The Licensor authorizes 128 | You to exercise the Licensed Rights in all media and formats whether now known 129 | or hereafter created, and to make technical modifications necessary to do 130 | so. The Licensor waives and/or agrees not to assert any right or authority 131 | to forbid You from making technical modifications necessary to exercise the 132 | Licensed Rights, including technical modifications necessary to circumvent 133 | Effective Technological Measures. For purposes of this Public License, simply 134 | making modifications authorized by this Section 2(a)(4) never produces Adapted 135 | Material. 136 | 137 | 5. Downstream recipients. 138 | 139 | A. Offer from the Licensor – Licensed Material. Every recipient of the Licensed 140 | Material automatically receives an offer from the Licensor to exercise the 141 | Licensed Rights under the terms and conditions of this Public License. 142 | 143 | B. No downstream restrictions. You may not offer or impose any additional 144 | or different terms or conditions on, or apply any Effective Technological 145 | Measures to, the Licensed Material if doing so restricts exercise of the Licensed 146 | Rights by any recipient of the Licensed Material. 147 | 148 | 6. No endorsement. Nothing in this Public License constitutes or may be construed 149 | as permission to assert or imply that You are, or that Your use of the Licensed 150 | Material is, connected with, or sponsored, endorsed, or granted official status 151 | by, the Licensor or others designated to receive attribution as provided in 152 | Section 3(a)(1)(A)(i). 153 | 154 | b. Other rights. 155 | 156 | 1. Moral rights, such as the right of integrity, are not licensed under this 157 | Public License, nor are publicity, privacy, and/or other similar personality 158 | rights; however, to the extent possible, the Licensor waives and/or agrees 159 | not to assert any such rights held by the Licensor to the limited extent necessary 160 | to allow You to exercise the Licensed Rights, but not otherwise. 161 | 162 | 2. Patent and trademark rights are not licensed under this Public License. 163 | 164 | 3. To the extent possible, the Licensor waives any right to collect royalties 165 | from You for the exercise of the Licensed Rights, whether directly or through 166 | a collecting society under any voluntary or waivable statutory or compulsory 167 | licensing scheme. In all other cases the Licensor expressly reserves any right 168 | to collect such royalties. 169 | 170 | Section 3 – License Conditions. 171 | 172 | Your exercise of the Licensed Rights is expressly made subject to the following 173 | conditions. 174 | 175 | a. Attribution. 176 | 177 | 1. If You Share the Licensed Material (including in modified form), You must: 178 | 179 | A. retain the following if it is supplied by the Licensor with the Licensed 180 | Material: 181 | 182 | i. identification of the creator(s) of the Licensed Material and any others 183 | designated to receive attribution, in any reasonable manner requested by the 184 | Licensor (including by pseudonym if designated); 185 | 186 | ii. a copyright notice; 187 | 188 | iii. a notice that refers to this Public License; 189 | 190 | iv. a notice that refers to the disclaimer of warranties; 191 | 192 | v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; 193 | 194 | B. indicate if You modified the Licensed Material and retain an indication 195 | of any previous modifications; and 196 | 197 | C. indicate the Licensed Material is licensed under this Public License, and 198 | include the text of, or the URI or hyperlink to, this Public License. 199 | 200 | 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner 201 | based on the medium, means, and context in which You Share the Licensed Material. 202 | For example, it may be reasonable to satisfy the conditions by providing a 203 | URI or hyperlink to a resource that includes the required information. 204 | 205 | 3. If requested by the Licensor, You must remove any of the information required 206 | by Section 3(a)(1)(A) to the extent reasonably practicable. 207 | 208 | 4. If You Share Adapted Material You produce, the Adapter's License You apply 209 | must not prevent recipients of the Adapted Material from complying with this 210 | Public License. 211 | 212 | Section 4 – Sui Generis Database Rights. 213 | 214 | Where the Licensed Rights include Sui Generis Database Rights that apply to 215 | Your use of the Licensed Material: 216 | 217 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, 218 | reuse, reproduce, and Share all or a substantial portion of the contents of 219 | the database; 220 | 221 | b. if You include all or a substantial portion of the database contents in 222 | a database in which You have Sui Generis Database Rights, then the database 223 | in which You have Sui Generis Database Rights (but not its individual contents) 224 | is Adapted Material; and 225 | 226 | c. You must comply with the conditions in Section 3(a) if You Share all or 227 | a substantial portion of the contents of the database. 228 | 229 | For the avoidance of doubt, this Section 4 supplements and does not replace 230 | Your obligations under this Public License where the Licensed Rights include 231 | other Copyright and Similar Rights. 232 | 233 | Section 5 – Disclaimer of Warranties and Limitation of Liability. 234 | 235 | a. Unless otherwise separately undertaken by the Licensor, to the extent possible, 236 | the Licensor offers the Licensed Material as-is and as-available, and makes 237 | no representations or warranties of any kind concerning the Licensed Material, 238 | whether express, implied, statutory, or other. This includes, without limitation, 239 | warranties of title, merchantability, fitness for a particular purpose, non-infringement, 240 | absence of latent or other defects, accuracy, or the presence or absence of 241 | errors, whether or not known or discoverable. Where disclaimers of warranties 242 | are not allowed in full or in part, this disclaimer may not apply to You. 243 | 244 | b. To the extent possible, in no event will the Licensor be liable to You 245 | on any legal theory (including, without limitation, negligence) or otherwise 246 | for any direct, special, indirect, incidental, consequential, punitive, exemplary, 247 | or other losses, costs, expenses, or damages arising out of this Public License 248 | or use of the Licensed Material, even if the Licensor has been advised of 249 | the possibility of such losses, costs, expenses, or damages. Where a limitation 250 | of liability is not allowed in full or in part, this limitation may not apply 251 | to You. 252 | 253 | c. The disclaimer of warranties and limitation of liability provided above 254 | shall be interpreted in a manner that, to the extent possible, most closely 255 | approximates an absolute disclaimer and waiver of all liability. 256 | 257 | Section 6 – Term and Termination. 258 | 259 | a. This Public License applies for the term of the Copyright and Similar Rights 260 | licensed here. However, if You fail to comply with this Public License, then 261 | Your rights under this Public License terminate automatically. 262 | 263 | b. Where Your right to use the Licensed Material has terminated under Section 264 | 6(a), it reinstates: 265 | 266 | 1. automatically as of the date the violation is cured, provided it is cured 267 | within 30 days of Your discovery of the violation; or 268 | 269 | 2. upon express reinstatement by the Licensor. 270 | 271 | c. For the avoidance of doubt, this Section 6(b) does not affect any right 272 | the Licensor may have to seek remedies for Your violations of this Public 273 | License. 274 | 275 | d. For the avoidance of doubt, the Licensor may also offer the Licensed Material 276 | under separate terms or conditions or stop distributing the Licensed Material 277 | at any time; however, doing so will not terminate this Public License. 278 | 279 | e. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. 280 | 281 | Section 7 – Other Terms and Conditions. 282 | 283 | a. The Licensor shall not be bound by any additional or different terms or 284 | conditions communicated by You unless expressly agreed. 285 | 286 | b. Any arrangements, understandings, or agreements regarding the Licensed 287 | Material not stated herein are separate from and independent of the terms 288 | and conditions of this Public License. 289 | 290 | Section 8 – Interpretation. 291 | 292 | a. For the avoidance of doubt, this Public License does not, and shall not 293 | be interpreted to, reduce, limit, restrict, or impose conditions on any use 294 | of the Licensed Material that could lawfully be made without permission under 295 | this Public License. 296 | 297 | b. To the extent possible, if any provision of this Public License is deemed 298 | unenforceable, it shall be automatically reformed to the minimum extent necessary 299 | to make it enforceable. If the provision cannot be reformed, it shall be severed 300 | from this Public License without affecting the enforceability of the remaining 301 | terms and conditions. 302 | 303 | c. No term or condition of this Public License will be waived and no failure 304 | to comply consented to unless expressly agreed to by the Licensor. 305 | 306 | d. Nothing in this Public License constitutes or may be interpreted as a limitation 307 | upon, or waiver of, any privileges and immunities that apply to the Licensor 308 | or You, including from the legal processes of any jurisdiction or authority. 309 | 310 | Creative Commons is not a party to its public licenses. Notwithstanding, Creative 311 | Commons may elect to apply one of its public licenses to material it publishes 312 | and in those instances will be considered the "Licensor." The text of the 313 | Creative Commons public licenses is dedicated to the public domain under the 314 | CC0 Public Domain Dedication. Except for the limited purpose of indicating 315 | that material is shared under a Creative Commons public license or as otherwise 316 | permitted by the Creative Commons policies published at creativecommons.org/policies, 317 | Creative Commons does not authorize the use of the trademark "Creative Commons" 318 | or any other trademark or logo of Creative Commons without its prior written 319 | consent including, without limitation, in connection with any unauthorized 320 | modifications to any of its public licenses or any other arrangements, understandings, 321 | or agreements concerning use of licensed material. For the avoidance of doubt, 322 | this paragraph does not form part of the public licenses. 323 | 324 | Creative Commons may be contacted at creativecommons.org. 325 | -------------------------------------------------------------------------------- /LICENSES/MIT.txt: -------------------------------------------------------------------------------- 1 | MIT License Copyright (c) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice (including the next 11 | paragraph) shall be included in all copies or substantial portions of the 12 | Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS 17 | OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19 | OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /LICENSES/Unlicense.txt: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute 4 | this software, either in source code form or as a compiled binary, for any 5 | purpose, commercial or non-commercial, and by any means. 6 | 7 | In jurisdictions that recognize copyright laws, the author or authors of this 8 | software dedicate any and all copyright interest in the software to the public 9 | domain. We make this dedication for the benefit of the public at large and 10 | to the detriment of our heirs and successors. We intend this dedication to 11 | be an overt act of relinquishment in perpetuity of all present and future 12 | rights to this software under copyright law. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS 17 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 18 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 19 | THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information, 20 | please refer to 21 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Introduction 2 | ============ 3 | 4 | .. image:: https://readthedocs.org/projects/adafruit-pureio/badge/?version=latest 5 | :target: https://adafruit-pureio.readthedocs.io/en/latest/ 6 | :alt: Documentation Status 7 | 8 | .. image:: https://img.shields.io/discord/327254708534116352.svg 9 | :target: https://adafru.it/discord 10 | :alt: Discord 11 | 12 | .. image:: https://github.com/adafruit/Adafruit_Python_PureIO/workflows/Build%20CI/badge.svg 13 | :target: https://github.com/adafruit/Adafruit_Python_PureIO/actions 14 | :alt: Build Status 15 | 16 | .. image:: https://img.shields.io/badge/code%20style-black-000000.svg 17 | :target: https://github.com/psf/black 18 | :alt: Code Style: Black 19 | 20 | Pure python (i.e. no native extensions) access to Linux IO including I2C and SPI. Drop in replacement for smbus and spidev modules. 21 | 22 | 23 | Dependencies 24 | ============= 25 | This driver depends on: 26 | 27 | * Python 3.5 or higher 28 | 29 | Installing from PyPI 30 | ===================== 31 | 32 | On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally `from 33 | PyPI `_. To install for current user: 34 | 35 | .. code-block:: shell 36 | 37 | pip3 install Adafruit-PureIO 38 | 39 | To install system-wide (this may be required in some cases): 40 | 41 | .. code-block:: shell 42 | 43 | sudo pip3 install Adafruit-PureIO 44 | 45 | To install in a virtual environment in your current project: 46 | 47 | .. code-block:: shell 48 | 49 | mkdir project-name && cd project-name 50 | python3 -m venv .env 51 | source .env/bin/activate 52 | pip3 install Adafruit-PureIO 53 | 54 | Contributing 55 | ============ 56 | 57 | Contributions are welcome! Please read our `Code of Conduct 58 | `_ 59 | before contributing to help this project stay welcoming. 60 | 61 | Documentation 62 | ============= 63 | 64 | For information on building library documentation, please check out `this guide `_. 65 | -------------------------------------------------------------------------------- /README.rst.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2020 Melissa LeBlanc-Williams for Adafruit Industries 2 | 3 | SPDX-License-Identifier: MIT 4 | -------------------------------------------------------------------------------- /docs/_static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_Python_PureIO/117f1f19f08a2c6edd11ef0281586ba5301dd649/docs/_static/favicon.ico -------------------------------------------------------------------------------- /docs/_static/favicon.ico.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries 2 | 3 | SPDX-License-Identifier: CC-BY-4.0 4 | -------------------------------------------------------------------------------- /docs/api.rst: -------------------------------------------------------------------------------- 1 | 2 | .. If you created a package, create one automodule per module in the package. 3 | 4 | .. If your library file(s) are nested in a directory (e.g. /adafruit_foo/foo.py) 5 | .. use this format as the module name: "adafruit_foo.foo" 6 | 7 | .. automodule:: Adafruit_PureIO.smbus 8 | :members: 9 | 10 | .. automodule:: Adafruit_PureIO.spi 11 | :members: 12 | -------------------------------------------------------------------------------- /docs/api.rst.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2020 Melissa LeBlanc-Williams for Adafruit Industries 2 | 3 | SPDX-License-Identifier: MIT 4 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # SPDX-FileCopyrightText: 2020 Melissa LeBlanc-Williams for Adafruit Industries 4 | # 5 | # SPDX-License-Identifier: MIT 6 | 7 | import os 8 | import sys 9 | 10 | sys.path.insert(0, os.path.abspath("..")) 11 | 12 | # -- General configuration ------------------------------------------------ 13 | 14 | # Add any Sphinx extension module names here, as strings. They can be 15 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 16 | # ones. 17 | extensions = [ 18 | "sphinx.ext.autodoc", 19 | "sphinx.ext.intersphinx", 20 | "sphinx.ext.napoleon", 21 | "sphinx.ext.todo", 22 | ] 23 | 24 | # TODO: Please Read! 25 | # Uncomment the below if you use native CircuitPython modules such as 26 | # digitalio, micropython and busio. List the modules you use. Without it, the 27 | # autodoc module docs will fail to generate with a warning. 28 | # autodoc_mock_imports = ["digitalio", "busio"] 29 | 30 | 31 | intersphinx_mapping = { 32 | "python": ("https://docs.python.org/3.5", None), 33 | "CircuitPython": ("https://circuitpython.readthedocs.io/en/latest/", None), 34 | } 35 | 36 | # Add any paths that contain templates here, relative to this directory. 37 | templates_path = ["_templates"] 38 | 39 | source_suffix = ".rst" 40 | 41 | # The master toctree document. 42 | master_doc = "index" 43 | 44 | # General information about the project. 45 | project = "Adafruit PureIO Library" 46 | copyright = "2020 Melissa LeBlanc-Williams" 47 | author = "Melissa LeBlanc-Williams" 48 | 49 | # The version info for the project you're documenting, acts as replacement for 50 | # |version| and |release|, also used in various other places throughout the 51 | # built documents. 52 | # 53 | # The short X.Y version. 54 | version = "1.0" 55 | # The full version, including alpha/beta/rc tags. 56 | release = "1.0" 57 | 58 | # The language for content autogenerated by Sphinx. Refer to documentation 59 | # for a list of supported languages. 60 | # 61 | # This is also used if you do content translation via gettext catalogs. 62 | # Usually you set "language" from the command line for these cases. 63 | language = "en" 64 | 65 | # List of patterns, relative to source directory, that match files and 66 | # directories to ignore when looking for source files. 67 | # This patterns also effect to html_static_path and html_extra_path 68 | exclude_patterns = [ 69 | "_build", 70 | "Thumbs.db", 71 | ".DS_Store", 72 | ".env", 73 | "CODE_OF_CONDUCT.md", 74 | ] 75 | 76 | # The reST default role (used for this markup: `text`) to use for all 77 | # documents. 78 | # 79 | default_role = "any" 80 | 81 | # If true, '()' will be appended to :func: etc. cross-reference text. 82 | # 83 | add_function_parentheses = True 84 | 85 | # The name of the Pygments (syntax highlighting) style to use. 86 | pygments_style = "sphinx" 87 | 88 | # If true, `todo` and `todoList` produce output, else they produce nothing. 89 | todo_include_todos = False 90 | 91 | # If this is True, todo emits a warning for each TODO entries. The default is False. 92 | todo_emit_warnings = True 93 | 94 | napoleon_numpy_docstring = False 95 | 96 | # -- Options for HTML output ---------------------------------------------- 97 | 98 | # The theme to use for HTML and HTML Help pages. See the documentation for 99 | # a list of builtin themes. 100 | # 101 | on_rtd = os.environ.get("READTHEDOCS", None) == "True" 102 | 103 | if not on_rtd: # only import and set the theme if we're building docs locally 104 | try: 105 | import sphinx_rtd_theme 106 | 107 | html_theme = "sphinx_rtd_theme" 108 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."] 109 | except: 110 | html_theme = "default" 111 | html_theme_path = ["."] 112 | else: 113 | html_theme_path = ["."] 114 | 115 | # Add any paths that contain custom static files (such as style sheets) here, 116 | # relative to this directory. They are copied after the builtin static files, 117 | # so a file named "default.css" will overwrite the builtin "default.css". 118 | html_static_path = ["_static"] 119 | 120 | # The name of an image file (relative to this directory) to use as a favicon of 121 | # the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 122 | # pixels large. 123 | # 124 | html_favicon = "_static/favicon.ico" 125 | 126 | # Output file base name for HTML help builder. 127 | htmlhelp_basename = "AdafruitPureioLibrarydoc" 128 | 129 | # -- Options for LaTeX output --------------------------------------------- 130 | 131 | latex_elements = { 132 | # The paper size ('letterpaper' or 'a4paper'). 133 | # 'papersize': 'letterpaper', 134 | # The font size ('10pt', '11pt' or '12pt'). 135 | # 'pointsize': '10pt', 136 | # Additional stuff for the LaTeX preamble. 137 | # 'preamble': '', 138 | # Latex figure (float) alignment 139 | # 'figure_align': 'htbp', 140 | } 141 | 142 | # Grouping the document tree into LaTeX files. List of tuples 143 | # (source start file, target name, title, 144 | # author, documentclass [howto, manual, or own class]). 145 | latex_documents = [ 146 | ( 147 | master_doc, 148 | "AdafruitPureIOLibrary.tex", 149 | "AdafruitPureIO Library Documentation", 150 | author, 151 | "manual", 152 | ), 153 | ] 154 | 155 | # -- Options for manual page output --------------------------------------- 156 | 157 | # One entry per manual page. List of tuples 158 | # (source start file, name, description, authors, manual section). 159 | man_pages = [ 160 | ( 161 | master_doc, 162 | "AdafruitPureIOlibrary", 163 | "Adafruit PureIO Library Documentation", 164 | [author], 165 | 1, 166 | ), 167 | ] 168 | 169 | # -- Options for Texinfo output ------------------------------------------- 170 | 171 | # Grouping the document tree into Texinfo files. List of tuples 172 | # (source start file, target name, title, author, 173 | # dir menu entry, description, category) 174 | texinfo_documents = [ 175 | ( 176 | master_doc, 177 | "AdafruitPureIOLibrary", 178 | "Adafruit PureIO Library Documentation", 179 | author, 180 | "AdafruitPureIOLibrary", 181 | "One line description of project.", 182 | "Miscellaneous", 183 | ), 184 | ] 185 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../README.rst 2 | 3 | Table of Contents 4 | ================= 5 | 6 | .. toctree:: 7 | :maxdepth: 4 8 | :hidden: 9 | 10 | self 11 | 12 | .. toctree:: 13 | :caption: API Reference 14 | :maxdepth: 3 15 | 16 | api 17 | 18 | .. toctree:: 19 | :caption: Tutorials 20 | 21 | .. toctree:: 22 | :caption: Related Products 23 | 24 | 25 | .. toctree:: 26 | :caption: Other Links 27 | 28 | Download 29 | CircuitPython Reference Documentation 30 | CircuitPython Support Forum 31 | Discord Chat 32 | Adafruit Learning System 33 | Adafruit Blog 34 | Adafruit Store 35 | 36 | Indices and tables 37 | ================== 38 | 39 | * :ref:`genindex` 40 | * :ref:`modindex` 41 | * :ref:`search` 42 | -------------------------------------------------------------------------------- /docs/index.rst.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2020 Melissa LeBlanc-Williams for Adafruit Industries 2 | 3 | SPDX-License-Identifier: MIT 4 | -------------------------------------------------------------------------------- /optional_requirements.txt: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2023 Alec Delaney, for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2023 Alec Delaney for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | [build-system] 6 | requires = [ 7 | "setuptools", 8 | "wheel", 9 | "setuptools-scm", 10 | ] 11 | 12 | [project] 13 | name = "Adafruit_PureIO" 14 | description = "Pure python (i.e. no native extensions) access to Linux IO including I2C and SPI. Drop in replacement for smbus and spidev modules." 15 | version = "0.0.0+auto.0" 16 | readme = "README.rst" 17 | authors = [ 18 | {name = "Adafruit Industries", email = "circuitpython@adafruit.com"} 19 | ] 20 | urls = {Homepage = "https://github.com/adafruit/Adafruit_Python_PureIO"} 21 | keywords = [ 22 | "adafruit", 23 | "blinka", 24 | "micropython", 25 | "pureio", 26 | "ioctl", 27 | "spi", 28 | "i2c", 29 | "python", 30 | ] 31 | license = {text = "MIT"} 32 | classifiers = [ 33 | "Development Status :: 3 - Alpha", 34 | "Intended Audience :: Developers", 35 | "Topic :: Software Development :: Libraries", 36 | "Topic :: System :: Hardware", 37 | "License :: OSI Approved :: MIT License", 38 | "Programming Language :: Python", 39 | "Programming Language :: Python :: 3", 40 | "Programming Language :: Python :: 3.4", 41 | "Programming Language :: Python :: 3.5", 42 | "Programming Language :: Python :: Implementation :: CPython", 43 | ] 44 | requires-python = ">=3.5.0" 45 | dynamic = ["dependencies", "optional-dependencies"] 46 | 47 | [tool.setuptools] 48 | packages = ["Adafruit_PureIO"] 49 | 50 | [tool.setuptools.dynamic] 51 | dependencies = {file = ["requirements.txt"]} 52 | optional-dependencies = {optional = {file = ["optional_requirements.txt"]}} 53 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_Python_PureIO/117f1f19f08a2c6edd11ef0281586ba5301dd649/requirements.txt -------------------------------------------------------------------------------- /tests/test_I2C.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2020 Melissa LeBlanc-Williams for Adafruit Industries 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | 6 | # Basic smbus test. This is pretty ugly and meant to be run against a ADS1x15 7 | # and some output inspected by a Saleae logic analyzer. TODO: Refactor into 8 | # something that can test without hardware? 9 | import binascii 10 | 11 | from Adafruit_PureIO import smbus 12 | 13 | 14 | DEVICE_ADDR = 0x48 15 | REGISTER = 0x01 16 | 17 | 18 | # Test open and close. 19 | i2c = smbus.SMBus() 20 | i2c.open(1) 21 | val = i2c.read_byte(DEVICE_ADDR) 22 | print("read_byte from 0x{0:0X}: 0x{1:0X}".format(REGISTER, val)) 23 | i2c.close() 24 | 25 | # Test initializer open. 26 | i2c = smbus.SMBus(1) 27 | val = i2c.read_byte(DEVICE_ADDR) 28 | print("read_byte from 0x{0:0X}: 0x{1:0X}".format(REGISTER, val)) 29 | i2c.close() 30 | 31 | # Test various data reads. 32 | with smbus.SMBus(1) as i2c: 33 | val = i2c.read_byte(DEVICE_ADDR) 34 | print("read_byte from 0x{0:0X}: 0x{1:0X}".format(REGISTER, val)) 35 | val = i2c.read_byte_data(DEVICE_ADDR, REGISTER) 36 | print("read_byte_data from 0x{0:0X}: 0x{1:0X}".format(REGISTER, val)) 37 | val = i2c.read_word_data(DEVICE_ADDR, REGISTER) 38 | print("read_word_data from 0x{0:0X}: 0x{1:04X}".format(REGISTER, val)) 39 | val = i2c.read_i2c_block_data(DEVICE_ADDR, REGISTER, 2) 40 | print( 41 | "read_i2c_block_data from 0x{0:0X}: 0x{1}".format( 42 | REGISTER, binascii.hexlify(val) 43 | ) 44 | ) 45 | 46 | # Test various data writes. 47 | with smbus.SMBus(1) as i2c: 48 | i2c.write_byte(DEVICE_ADDR, REGISTER) 49 | i2c.write_byte_data(DEVICE_ADDR, REGISTER, 0x85) 50 | i2c.write_word_data(DEVICE_ADDR, REGISTER, 0x8385) 51 | i2c.write_i2c_block_data(DEVICE_ADDR, REGISTER, [0x85, 0x83]) 52 | # i2c.write_block_data(DEVICE_ADDR, REGISTER, [0x85, 0x83]) 53 | i2c.write_quick(DEVICE_ADDR) 54 | 55 | # Process call test. 56 | with smbus.SMBus(1) as i2c: 57 | val = i2c.process_call(DEVICE_ADDR, REGISTER, 0x8385) 58 | print("process_call from 0x{0:0X}: 0x{1:04X}".format(REGISTER, val)) 59 | --------------------------------------------------------------------------------