Massive pylinting session and added Github Actions
This commit is contained in:
parent
85e40fd98d
commit
a79e37b272
83 changed files with 2121 additions and 1354 deletions
50
.github/workflows/build.yml
vendored
Normal file
50
.github/workflows/build.yml
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
name: Build CI
|
||||
|
||||
on: [pull_request, push]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- name: Translate Repo Name For Build Tools filename_prefix
|
||||
id: repo-name
|
||||
run: echo ::set-output name=repo-name::Adafruit-Blinka
|
||||
- name: Set up Python 3.6
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: 3.6
|
||||
- name: Versions
|
||||
run: |
|
||||
python3 --version
|
||||
- name: Checkout Current Repo
|
||||
uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: true
|
||||
- name: Checkout tools repo
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: adafruit/actions-ci-circuitpython-libs
|
||||
path: actions-ci
|
||||
- name: Install dependencies
|
||||
# (e.g. - apt-get: gettext, etc; pip: circuitpython-build-tools, requirements.txt; etc.)
|
||||
run: |
|
||||
source actions-ci/install.sh
|
||||
- name: Pip install pylint, black, & Sphinx
|
||||
run: |
|
||||
pip install --force-reinstall pylint black==19.10b0 Sphinx sphinx-rtd-theme
|
||||
- name: Library version
|
||||
run: git describe --dirty --always --tags
|
||||
- name: Check formatting
|
||||
run: |
|
||||
black --check --target-version=py35 .
|
||||
- name: PyLint
|
||||
run: |
|
||||
pylint src/**/*.py
|
||||
([[ ! -d "examples" ]] || pylint --disable=missing-docstring,invalid-name,bad-whitespace $( find . -path "./examples/*.py" ))
|
||||
- name: Build docs
|
||||
working-directory: docs
|
||||
run: sphinx-build -E -W -b html . _build/html
|
||||
33
.github/workflows/release.yml
vendored
Normal file
33
.github/workflows/release.yml
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
name: Release Actions
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
upload-pypi:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Check For setup.py
|
||||
id: need-pypi
|
||||
run: |
|
||||
echo ::set-output name=setup-py::$( find . -wholename './setup.py' )
|
||||
- name: Set up Python
|
||||
if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Install dependencies
|
||||
if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install setuptools wheel twine
|
||||
- name: Build and publish
|
||||
if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
|
||||
env:
|
||||
TWINE_USERNAME: ${{ secrets.pypi_username }}
|
||||
TWINE_PASSWORD: ${{ secrets.pypi_password }}
|
||||
run: |
|
||||
python setup.py sdist
|
||||
twine upload dist/*
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -4,7 +4,6 @@ __pycache__
|
|||
_build
|
||||
*.pyc
|
||||
.env
|
||||
build*
|
||||
bundles
|
||||
*.DS_Store
|
||||
.eggs
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# A comma-separated list of package or module names from where C extensions may
|
||||
# be loaded. Extensions are loading into the active Python interpreter and may
|
||||
# run arbitrary code
|
||||
extension-pkg-whitelist=
|
||||
extension-pkg-whitelist=hid
|
||||
|
||||
# Add files or directories to the blacklist. They should be base names, not
|
||||
# paths.
|
||||
|
|
@ -52,7 +52,7 @@ confidence=
|
|||
# no Warning level messages displayed, use"--disable=all --enable=classes
|
||||
# --disable=W"
|
||||
# disable=import-error,print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call
|
||||
disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error
|
||||
disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error,bad-continuation,invalid-name
|
||||
|
||||
# Enable the message, report, category or checker with the given id(s). You can
|
||||
# either give multiple identifier separated by comma (,) or put this option
|
||||
|
|
|
|||
27
.travis.yml
27
.travis.yml
|
|
@ -1,27 +0,0 @@
|
|||
dist: trusty
|
||||
sudo: false
|
||||
language: python
|
||||
python:
|
||||
- "3.6"
|
||||
|
||||
cache:
|
||||
pip: true
|
||||
|
||||
deploy:
|
||||
- provider: pypi
|
||||
user: adafruit-travis
|
||||
password:
|
||||
secure: UHEnpdeuxFrqSrrSKheh5fB8M5LA7JKmKkAgTy5YHvk/y3sTHHST5cgHg5s5zYSLG3WRrQgnUcf8ISEs6Sb22wtCi81nIhFfML97o/TD+lUSU+lMmbXiLvkMWhkVjGI6P8f5vXc655XYU0W84z9tI4aTKFVKC4pI4qY4XIDe3X7kvQoeRZdTZX35gCWBw9Hshhfc5AENJvRiQqOK/RXiZN4PS+jVFIG0MjSNZ1oO8/Bks//AGHacZuI+5sl3XTbeefiXLmbKsxqEir754GGs04ZgP7OAY4DHgQC2aigdXfnZEcWoWkfU+Hpz4FicFwYqsKfESVwN0Y/Dx4J06YISPEAagUtm0W63qmZ2GSxLmwWBNZ8hDiLaaVEmK9T6q+iw3CPTicC5/35gL+wab2P7thlCA7GHDYg9QfjthcT35Wc0cS+/iQ1w8uOA3aydjXMgiuzydqpViB+r7GmTxHp8qIwAQIYuy6GIY/tqgUUWZ5sjlkmBZTvtbqXYndQk4uvKifsqdbGJxvZh27+BPGSnAe3fIdxAGvGyLH2Ic58NANHrcV3iXMKkhEG3u7pka78uuZJbTnN1KUvk8XgrTv3Xk3gM5ZIn5HCadcXT6i6VMr0ELZCRmR1cng7d03NsXPFFz3LwjWr4MH34ON5HdQuk/X4bhF/IWxSZvxfSZW8C5mE=
|
||||
on:
|
||||
tags: true
|
||||
|
||||
install:
|
||||
- sudo apt-get install libudev-dev libusb-1.0
|
||||
- pip install -r requirements.txt
|
||||
- pip install --force-reinstall pylint==1.9.2
|
||||
- pip install circuitpython-build-tools Sphinx sphinx-rtd-theme
|
||||
|
||||
script:
|
||||
- pylint src/**/*.py
|
||||
- ([[ ! -d "examples" ]] || pylint --disable=missing-docstring,invalid-name,bad-whitespace examples/*.py)
|
||||
- cd docs && sphinx-build -E -W -b html . _build/html && cd ..
|
||||
85
docs/conf.py
85
docs/conf.py
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
import os
|
||||
import sys
|
||||
sys.path.insert(0, os.path.abspath('../src'))
|
||||
|
||||
sys.path.insert(0, os.path.abspath("../src"))
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
|
|
@ -10,9 +11,9 @@ sys.path.insert(0, os.path.abspath('../src'))
|
|||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.intersphinx',
|
||||
'sphinx.ext.todo',
|
||||
"sphinx.ext.autodoc",
|
||||
"sphinx.ext.intersphinx",
|
||||
"sphinx.ext.todo",
|
||||
]
|
||||
|
||||
# Uncomment the below if you use native CircuitPython modules such as
|
||||
|
|
@ -20,30 +21,32 @@ extensions = [
|
|||
# autodoc module docs will fail to generate with a warning.
|
||||
autodoc_mock_imports = ["machine", "Adafruit_GPIO"]
|
||||
|
||||
intersphinx_mapping = {'python': ('https://docs.python.org/3.4', None),
|
||||
'CircuitPython': ('https://circuitpython.readthedocs.io/en/latest/', None)}
|
||||
intersphinx_mapping = {
|
||||
"python": ("https://docs.python.org/3.4", None),
|
||||
"CircuitPython": ("https://circuitpython.readthedocs.io/en/latest/", None),
|
||||
}
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
templates_path = ["_templates"]
|
||||
|
||||
source_suffix = '.rst'
|
||||
source_suffix = ".rst"
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
master_doc = "index"
|
||||
|
||||
# General information about the project.
|
||||
project = u'Adafruit Blinka Library'
|
||||
copyright = u'2017 cefn'
|
||||
author = u'cefn'
|
||||
project = "Adafruit Blinka Library"
|
||||
copyright = "2017 cefn"
|
||||
author = "cefn"
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = u'1.0.0'
|
||||
version = "1.0.0"
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = u'1.0.0'
|
||||
release = "1.0.0"
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
|
@ -55,7 +58,7 @@ language = None
|
|||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This patterns also effect to html_static_path and html_extra_path
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '.env', 'CODE_OF_CONDUCT.md']
|
||||
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", ".env", "CODE_OF_CONDUCT.md"]
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all
|
||||
# documents.
|
||||
|
|
@ -67,7 +70,7 @@ default_role = "any"
|
|||
add_function_parentheses = True
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
pygments_style = "sphinx"
|
||||
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = False
|
||||
|
|
@ -81,26 +84,27 @@ todo_emit_warnings = True
|
|||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
|
||||
on_rtd = os.environ.get("READTHEDOCS", None) == "True"
|
||||
|
||||
if not on_rtd: # only import and set the theme if we're building docs locally
|
||||
try:
|
||||
import sphinx_rtd_theme
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), '.']
|
||||
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."]
|
||||
except:
|
||||
html_theme = 'default'
|
||||
html_theme_path = ['.']
|
||||
html_theme = "default"
|
||||
html_theme_path = ["."]
|
||||
else:
|
||||
html_theme_path = ['.']
|
||||
html_theme_path = ["."]
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
html_static_path = ["_static"]
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'AdafruitBlinkaLibrarydoc'
|
||||
htmlhelp_basename = "AdafruitBlinkaLibrarydoc"
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
|
|
@ -108,15 +112,12 @@ latex_elements = {
|
|||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
|
|
@ -126,8 +127,13 @@ latex_elements = {
|
|||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'AdafruitBlinkaLibrary.tex', u'AdafruitBlinka Library Documentation',
|
||||
author, 'manual'),
|
||||
(
|
||||
master_doc,
|
||||
"AdafruitBlinkaLibrary.tex",
|
||||
"AdafruitBlinka Library Documentation",
|
||||
author,
|
||||
"manual",
|
||||
),
|
||||
]
|
||||
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
|
@ -135,8 +141,13 @@ latex_documents = [
|
|||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'AdafruitBlinkalibrary', u'Adafruit Blinka Library Documentation',
|
||||
[author], 1)
|
||||
(
|
||||
master_doc,
|
||||
"AdafruitBlinkalibrary",
|
||||
"Adafruit Blinka Library Documentation",
|
||||
[author],
|
||||
1,
|
||||
)
|
||||
]
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
|
@ -145,7 +156,13 @@ man_pages = [
|
|||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'AdafruitBlinkaLibrary', u'Adafruit Blinka Library Documentation',
|
||||
author, 'AdafruitBlinkaLibrary', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
(
|
||||
master_doc,
|
||||
"AdafruitBlinkaLibrary",
|
||||
"Adafruit Blinka Library Documentation",
|
||||
author,
|
||||
"AdafruitBlinkaLibrary",
|
||||
"One line description of project.",
|
||||
"Miscellaneous",
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ if not 0x18 in i2c.scan():
|
|||
print("Didn't find MCP9808")
|
||||
exit()
|
||||
|
||||
|
||||
def temp_c(data):
|
||||
value = data[0] << 8 | data[1]
|
||||
temp = (value & 0xFFF) / 16.0
|
||||
|
|
@ -19,6 +20,7 @@ def temp_c(data):
|
|||
temp -= 256.0
|
||||
return temp
|
||||
|
||||
|
||||
while True:
|
||||
i2c.writeto(0x18, bytes([0x05]), stop=False)
|
||||
result = bytearray(2)
|
||||
|
|
|
|||
|
|
@ -9,8 +9,10 @@ import digitalio
|
|||
|
||||
print("hello blinka!")
|
||||
|
||||
print("Found system type: %s (sys.plaform %s implementation %s) " %
|
||||
(agnostic_board, sys.platform, sys.implementation.name))
|
||||
print(
|
||||
"Found system type: %s (sys.plaform %s implementation %s) "
|
||||
% (agnostic_board, sys.platform, sys.implementation.name)
|
||||
)
|
||||
|
||||
print("board contents: ", dir(board))
|
||||
|
||||
|
|
|
|||
76
setup.py
76
setup.py
|
|
@ -14,52 +14,66 @@ here = os.path.abspath(os.path.dirname(__file__))
|
|||
|
||||
# Import the README and use it as the long-description.
|
||||
# Note: this will only work if 'README.md' is present in your MANIFEST.in file!
|
||||
with io.open(os.path.join(here, 'README.rst'), encoding='utf-8') as f:
|
||||
long_description = '\n' + f.read()
|
||||
with io.open(os.path.join(here, "README.rst"), encoding="utf-8") as f:
|
||||
long_description = "\n" + f.read()
|
||||
|
||||
board_reqs = []
|
||||
if os.path.exists('/proc/device-tree/compatible'):
|
||||
with open('/proc/device-tree/compatible', 'rb') as f:
|
||||
if os.path.exists("/proc/device-tree/compatible"):
|
||||
with open("/proc/device-tree/compatible", "rb") as f:
|
||||
compat = f.read()
|
||||
if b'nvidia,tegra' in compat:
|
||||
board_reqs = ['Jetson.GPIO']
|
||||
if b'brcm,bcm2835' in compat or \
|
||||
b'brcm,bcm2836' in compat or \
|
||||
b'brcm,bcm2837' in compat or \
|
||||
b'brcm,bcm2838' in compat:
|
||||
board_reqs = ['RPi.GPIO', 'rpi_ws281x>=4.0.0']
|
||||
if b"nvidia,tegra" in compat:
|
||||
board_reqs = ["Jetson.GPIO"]
|
||||
if (
|
||||
b"brcm,bcm2835" in compat
|
||||
or b"brcm,bcm2836" in compat
|
||||
or b"brcm,bcm2837" in compat
|
||||
or b"brcm,bcm2838" in compat
|
||||
):
|
||||
board_reqs = ["RPi.GPIO", "rpi_ws281x>=4.0.0"]
|
||||
|
||||
setup(
|
||||
name='Adafruit-Blinka',
|
||||
name="Adafruit-Blinka",
|
||||
use_scm_version=True,
|
||||
setup_requires=["setuptools_scm"],
|
||||
description='CircuitPython APIs for non-CircuitPython versions of Python such as CPython on Linux and MicroPython.',
|
||||
description="CircuitPython APIs for non-CircuitPython versions of Python such as CPython on Linux and MicroPython.",
|
||||
long_description=long_description,
|
||||
long_description_content_type='text/x-rst',
|
||||
author='Adafruit Industries',
|
||||
author_email='circuitpython@adafruit.com',
|
||||
python_requires='>=3.4.0',
|
||||
url='https://github.com/adafruit/Adafruit_Blinka',
|
||||
package_dir={'': 'src'},
|
||||
long_description_content_type="text/x-rst",
|
||||
author="Adafruit Industries",
|
||||
author_email="circuitpython@adafruit.com",
|
||||
python_requires=">=3.5.0",
|
||||
url="https://github.com/adafruit/Adafruit_Blinka",
|
||||
package_dir={"": "src"},
|
||||
packages=find_packages("src"),
|
||||
# py_modules lists top-level single file packages to include.
|
||||
# find_packages only finds packages in directories with __init__.py files.
|
||||
py_modules=['analogio', 'bitbangio', 'board', 'busio', 'digitalio', 'micropython', 'pulseio', 'neopixel_write'],
|
||||
package_data={'adafruit_blinka.microcontroller.bcm283x.pulseio': ['libgpiod_pulsein']},
|
||||
py_modules=[
|
||||
"analogio",
|
||||
"bitbangio",
|
||||
"board",
|
||||
"busio",
|
||||
"digitalio",
|
||||
"micropython",
|
||||
"pulseio",
|
||||
"neopixel_write",
|
||||
],
|
||||
package_data={
|
||||
"adafruit_blinka.microcontroller.bcm283x.pulseio": ["libgpiod_pulsein"]
|
||||
},
|
||||
install_requires=[
|
||||
"Adafruit-PlatformDetect>=2.6.0",
|
||||
"Adafruit-PureIO>=1.1.4",
|
||||
"Adafruit-PlatformDetect>=2.7.0",
|
||||
"Adafruit-PureIO>=1.1.5",
|
||||
"sysv_ipc; platform_system != 'Windows' and platform_machine != 'mips'",
|
||||
"pyftdi>=0.40.0"
|
||||
] + board_reqs,
|
||||
license='MIT',
|
||||
"pyftdi>=0.40.0",
|
||||
]
|
||||
+ board_reqs,
|
||||
license="MIT",
|
||||
classifiers=[
|
||||
# Trove classifiers
|
||||
# Full list: https://pypi.python.org/pypi?%3Aaction=list_classifiers
|
||||
'License :: OSI Approved :: MIT License',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: Implementation :: MicroPython',
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.5",
|
||||
"Programming Language :: Python :: Implementation :: MicroPython",
|
||||
],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
VERSION = (1, 0, 0)
|
||||
|
||||
__version__ = '.'.join(map(str, VERSION))
|
||||
__version__ = ".".join(map(str, VERSION))
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@
|
|||
* Author(s): cefn
|
||||
"""
|
||||
|
||||
class Enum():
|
||||
|
||||
class Enum:
|
||||
"""
|
||||
Object supporting CircuitPython-style of static symbols
|
||||
as seen with Direction.OUTPUT, Pull.UP
|
||||
|
|
@ -37,6 +38,7 @@ class Enum():
|
|||
|
||||
class ContextManaged:
|
||||
"""An object that automatically deinitializes hardware with a context manager."""
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
|
|
@ -47,11 +49,13 @@ class ContextManaged:
|
|||
def deinit(self):
|
||||
"""Free any hardware used by the object."""
|
||||
return
|
||||
|
||||
# pylint: enable=no-self-use
|
||||
|
||||
|
||||
class Lockable(ContextManaged):
|
||||
"""An object that must be locked to prevent collisions on a microcontroller resource."""
|
||||
|
||||
_locked = False
|
||||
|
||||
def try_lock(self):
|
||||
|
|
@ -68,8 +72,13 @@ class Lockable(ContextManaged):
|
|||
else:
|
||||
raise ValueError("Not locked")
|
||||
|
||||
|
||||
def patch_system():
|
||||
"""Patch modules that may be different due to the platform."""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
import sys
|
||||
from adafruit_blinka.agnostic import time
|
||||
sys.modules['time'] = time
|
||||
|
||||
# pylint: enable=import-outside-toplevel
|
||||
|
||||
sys.modules["time"] = time
|
||||
|
|
|
|||
|
|
@ -12,15 +12,46 @@ elif agnostic.implementation == "micropython":
|
|||
from utime import sleep
|
||||
|
||||
from ucollections import namedtuple
|
||||
_struct_time = namedtuple("struct_time", ("tm_year", "tm_mon", "tm_mday",
|
||||
"tm_hour", "tm_min", "tm_sec",
|
||||
"tm_wday", "tm_yday", "tm_isdst"))
|
||||
|
||||
_struct_time = namedtuple(
|
||||
"struct_time",
|
||||
(
|
||||
"tm_year",
|
||||
"tm_mon",
|
||||
"tm_mday",
|
||||
"tm_hour",
|
||||
"tm_min",
|
||||
"tm_sec",
|
||||
"tm_wday",
|
||||
"tm_yday",
|
||||
"tm_isdst",
|
||||
),
|
||||
)
|
||||
|
||||
# pylint: disable=too-many-arguments
|
||||
def _marshal_time(tm_year, tm_mon, tm_mday, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=-1,
|
||||
tm_yday=-1, tm_isdst=-1):
|
||||
def _marshal_time(
|
||||
tm_year,
|
||||
tm_mon,
|
||||
tm_mday,
|
||||
tm_hour=0,
|
||||
tm_min=0,
|
||||
tm_sec=0,
|
||||
tm_wday=-1,
|
||||
tm_yday=-1,
|
||||
tm_isdst=-1,
|
||||
):
|
||||
"""Construct struct_time with default values."""
|
||||
_struct_time(tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, tm_wday, tm_yday, tm_isdst)
|
||||
_struct_time(
|
||||
tm_year,
|
||||
tm_mon,
|
||||
tm_mday,
|
||||
tm_hour,
|
||||
tm_min,
|
||||
tm_sec,
|
||||
tm_wday,
|
||||
tm_yday,
|
||||
tm_isdst,
|
||||
)
|
||||
|
||||
def struct_time(time_tuple):
|
||||
"""Create a struct_time"""
|
||||
|
|
@ -29,6 +60,7 @@ elif agnostic.implementation == "micropython":
|
|||
# pylint: disable=invalid-name
|
||||
_total_ms = 0
|
||||
_prev_ticks_ms = utime.ticks_ms()
|
||||
|
||||
def monotonic():
|
||||
"""A monotonically increasing time in seconds. No defined start time."""
|
||||
# Assumes that monotonic is called more frequently than the wraparound of micropython's
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
"""Pin definitions for the Binho Nova"""
|
||||
from adafruit_blinka.microcontroller.nova import pin
|
||||
|
||||
IO0 = pin.IO0
|
||||
|
|
|
|||
|
|
@ -22,4 +22,3 @@ MOSI = pin.ECSPI1_MOSI
|
|||
SCLK = pin.ECSPI1_SCLK
|
||||
SCK = pin.ECSPI1_SCLK
|
||||
SS0 = pin.ECSPI1_SS0
|
||||
|
||||
|
|
|
|||
|
|
@ -40,4 +40,3 @@ SCLK = pin.SPI0_SCLK
|
|||
MOSI = pin.SPI0_MOSI
|
||||
MISO = pin.SPI0_MISO
|
||||
SPI_CS = pin.SPI0_CS
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
"""Pin definitions for the FTDI FT232H"""
|
||||
from adafruit_blinka.microcontroller.ft232h import pin
|
||||
|
||||
D4 = pin.D4
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
"""Pin definitions for the Giant Board"""
|
||||
from adafruit_blinka.microcontroller.sama5 import pin
|
||||
|
||||
PD23 = pin.PD23
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ SPI0_DIN = pin.SPI0_DIN
|
|||
UART1_TXD = pin.UART1_TXD
|
||||
SPI0_CS = pin.SPI0_CS
|
||||
UART1_RXD = pin.UART1_RXD
|
||||
SPIO0_DOUT = pin.SPIO0_DOUT
|
||||
SPI0_DOUT = pin.SPI0_DOUT
|
||||
I2C0_SCL = pin.I2C0_SCL
|
||||
I2C0_SDA = pin.I2C0_SDA
|
||||
|
||||
|
|
@ -35,4 +35,3 @@ SCLK = pin.SPI0_SCLK
|
|||
MOSI = pin.SPI0_DOUT
|
||||
MISO = pin.SPI0_DIN
|
||||
SPI_CS = pin.SPI0_CS
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
"""Pin definitions for the MicroChip MCP2221"""
|
||||
from adafruit_blinka.microcontroller.mcp2221 import pin
|
||||
|
||||
G0 = pin.G0
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
"""Allwinner A33 pin names"""
|
||||
|
||||
from adafruit_blinka.microcontroller.generic_linux.libgpiod_pin import Pin
|
||||
|
||||
PB0 = Pin(32) # PB0/UART2_TX/UART0_TX/PB_EINT0
|
||||
|
|
@ -33,14 +35,10 @@ SPI0_MISO = PH9
|
|||
|
||||
|
||||
# ordered as i2cId, sclId, sdaId
|
||||
i2cPorts = (
|
||||
(0, TWI1_SCL, TWI1_SDA),
|
||||
)
|
||||
i2cPorts = ((0, TWI1_SCL, TWI1_SDA),)
|
||||
|
||||
# ordered as spiId, sckId, mosiId, misoId
|
||||
spiPorts = (
|
||||
(0, SPI0_SCLK, SPI0_MOSI, SPI0_MISO),
|
||||
)
|
||||
spiPorts = ((0, SPI0_SCLK, SPI0_MOSI, SPI0_MISO),)
|
||||
|
||||
# ordered as uartId, txId, rxId
|
||||
uartPorts = (
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
"""Allwinner A64 pin names"""
|
||||
from adafruit_blinka.microcontroller.generic_linux.libgpiod_pin import Pin
|
||||
|
||||
PB0 = Pin((1, 32))
|
||||
|
|
@ -72,10 +73,7 @@ PL9 = Pin((0, 9))
|
|||
PL10 = Pin((0, 10))
|
||||
|
||||
# ordered as i2cId, sclId, sdaId
|
||||
i2cPorts = (
|
||||
(1, TWI1_SCL, TWI1_SDA),
|
||||
(2, TWI2_SCL, TWI2_SDA)
|
||||
)
|
||||
i2cPorts = ((1, TWI1_SCL, TWI1_SDA), (2, TWI2_SCL, TWI2_SDA))
|
||||
|
||||
# ordered as spiId, sckId, mosiId, misoId
|
||||
spiPorts = (
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
"""Allwinner H3 pin names"""
|
||||
from adafruit_blinka.microcontroller.generic_linux.libgpiod_pin import Pin
|
||||
|
||||
PA0 = Pin(0)
|
||||
|
|
@ -55,15 +56,11 @@ PG12 = Pin(204)
|
|||
PG13 = Pin(205)
|
||||
|
||||
|
||||
i2cPorts = (
|
||||
(0, TWI0_SCL, TWI0_SDA),
|
||||
)
|
||||
i2cPorts = ((0, TWI0_SCL, TWI0_SDA),)
|
||||
# ordered as spiId, sckId, mosiId, misoId
|
||||
spiPorts = (
|
||||
(0, SPI0_SCLK, SPI0_MOSI, SPI0_MISO),
|
||||
(1, SPI1_SCLK, SPI1_MOSI, SPI1_MISO),
|
||||
)
|
||||
# ordered as uartId, txId, rxId
|
||||
uartPorts = (
|
||||
(3, UART3_TX, UART3_RX),
|
||||
)
|
||||
uartPorts = ((3, UART3_TX, UART3_RX),)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
"""AM335x pin names"""
|
||||
import Adafruit_BBIO.GPIO as GPIO
|
||||
|
||||
# Pins dont exist in CPython so...lets make our own!
|
||||
|
||||
class Pin:
|
||||
"""Pins dont exist in CPython so...lets make our own!"""
|
||||
|
||||
IN = 0
|
||||
OUT = 1
|
||||
LOW = 0
|
||||
|
|
@ -24,7 +27,8 @@ class Pin:
|
|||
return self.id == other
|
||||
|
||||
def init(self, mode=IN, pull=None):
|
||||
if mode != None:
|
||||
"""Initialize the Pin"""
|
||||
if mode is not None:
|
||||
if mode == self.IN:
|
||||
self._mode = self.IN
|
||||
GPIO.setup(self.id, GPIO.IN)
|
||||
|
|
@ -33,7 +37,7 @@ class Pin:
|
|||
GPIO.setup(self.id, GPIO.OUT)
|
||||
else:
|
||||
raise RuntimeError("Invalid mode for pin: %s" % self.id)
|
||||
if pull != None:
|
||||
if pull is not None:
|
||||
if self._mode != self.IN:
|
||||
raise RuntimeError("Cannot set pull resistor on output")
|
||||
if pull == self.PULL_UP:
|
||||
|
|
@ -44,7 +48,8 @@ class Pin:
|
|||
raise RuntimeError("Invalid pull for pin: %s" % self.id)
|
||||
|
||||
def value(self, val=None):
|
||||
if val != None:
|
||||
"""Set or return the Pin Value"""
|
||||
if val is not None:
|
||||
if val == self.LOW:
|
||||
self._value = val
|
||||
GPIO.output(self.id, val)
|
||||
|
|
@ -53,7 +58,7 @@ class Pin:
|
|||
GPIO.output(self.id, val)
|
||||
else:
|
||||
raise RuntimeError("Invalid value for pin")
|
||||
else:
|
||||
return None
|
||||
return GPIO.input(self.id)
|
||||
|
||||
|
||||
|
|
@ -62,128 +67,128 @@ class Pin:
|
|||
|
||||
# PocketBeagle
|
||||
# P1_1 = SYS VIN # VIN_AC
|
||||
P1_2 = Pin('P1_2') # GPIO2_23 - GPIO_87
|
||||
P1_3 = Pin('P1_3') # USB1_VBUS_OUT - (silkscreen: USB1 V_EN)
|
||||
P1_4 = Pin('P1_4') # GPIO2_25 - GPIO_89
|
||||
P1_2 = Pin("P1_2") # GPIO2_23 - GPIO_87
|
||||
P1_3 = Pin("P1_3") # USB1_VBUS_OUT - (silkscreen: USB1 V_EN)
|
||||
P1_4 = Pin("P1_4") # GPIO2_25 - GPIO_89
|
||||
# P1_5 = USB VBUS # USB1_VBUS_IN
|
||||
P1_6 = Pin('P1_6') # SPI0_CS0 - GPIO_5
|
||||
P1_6 = Pin("P1_6") # SPI0_CS0 - GPIO_5
|
||||
# P1_7 = USB VIN # VIN-USB
|
||||
P1_8 = Pin('P1_8') # SPI0_SCLK - GPIO_2
|
||||
P1_8 = Pin("P1_8") # SPI0_SCLK - GPIO_2
|
||||
# P1_9 = USB1 DN # USB1-DN
|
||||
P1_10 = Pin('P1_10') # SPI0_D0 - GPIO_3
|
||||
P1_10 = Pin("P1_10") # SPI0_D0 - GPIO_3
|
||||
# P1_11 = USB1 DP # USB1-DP
|
||||
P1_12 = Pin('P1_12') # SPI0_D1 - GPIO_4
|
||||
P1_12 = Pin("P1_12") # SPI0_D1 - GPIO_4
|
||||
# P1_13 = USB1 ID # USB1-ID
|
||||
# P1_14 = SYS 3.3V # VOUT-3.3V
|
||||
# P1_15 = SYS GND # GND
|
||||
# P1_16 = SYS GND # GND
|
||||
# P1_17 = AIN 1.8V REF- # VREFN
|
||||
# P1_18 = AIN 1.8V REF+ # VREFP
|
||||
P1_19 = Pin('P1_19') # AIN0
|
||||
P1_20 = Pin('P1_20') # GPIO0_20 - GPIO_20
|
||||
P1_21 = Pin('P1_21') # AIN1
|
||||
P1_19 = Pin("P1_19") # AIN0
|
||||
P1_20 = Pin("P1_20") # GPIO0_20 - GPIO_20
|
||||
P1_21 = Pin("P1_21") # AIN1
|
||||
# P1_22 = SYS GND # GND
|
||||
P1_23 = Pin('P1_23') # AIN2
|
||||
P1_23 = Pin("P1_23") # AIN2
|
||||
# P1_22 = SYS VOUT # VOUT-5V
|
||||
P1_25 = Pin('P1_25') # AIN3
|
||||
P1_26 = Pin('P1_26') # I2C2_SDA - GPIO_12
|
||||
P1_27 = Pin('P1_27') # AIN4
|
||||
P1_28 = Pin('P1_28') # I2C2_SCL - GPIO_13
|
||||
P1_29 = Pin('P1_29') # GPIO3_21 - GPIO_117
|
||||
P1_30 = Pin('P1_30') # UART0_TXD - GPIO_43
|
||||
P1_31 = Pin('P1_31') # GPIO3_18 - GPIO_114
|
||||
P1_32 = Pin('P1_32') # UART0_RXD - GPIO_42
|
||||
P1_33 = Pin('P1_33') # GPIO3_15 - GPIO_111
|
||||
P1_34 = Pin('P1_34') # GPIO0_26 - GPIO_26
|
||||
P1_35 = Pin('P1_35') # GPIO2_24 - GPIO_88
|
||||
P1_36 = Pin('P1_36') # EHRPWM0A - GPIO_110
|
||||
P1_25 = Pin("P1_25") # AIN3
|
||||
P1_26 = Pin("P1_26") # I2C2_SDA - GPIO_12
|
||||
P1_27 = Pin("P1_27") # AIN4
|
||||
P1_28 = Pin("P1_28") # I2C2_SCL - GPIO_13
|
||||
P1_29 = Pin("P1_29") # GPIO3_21 - GPIO_117
|
||||
P1_30 = Pin("P1_30") # UART0_TXD - GPIO_43
|
||||
P1_31 = Pin("P1_31") # GPIO3_18 - GPIO_114
|
||||
P1_32 = Pin("P1_32") # UART0_RXD - GPIO_42
|
||||
P1_33 = Pin("P1_33") # GPIO3_15 - GPIO_111
|
||||
P1_34 = Pin("P1_34") # GPIO0_26 - GPIO_26
|
||||
P1_35 = Pin("P1_35") # GPIO2_24 - GPIO_88
|
||||
P1_36 = Pin("P1_36") # EHRPWM0A - GPIO_110
|
||||
|
||||
|
||||
P2_1 = Pin('P2_1') # EHRPWM1A - GPIO_50
|
||||
P2_2 = Pin('P2_2') # GPIO1_27 - GPIO_59
|
||||
P2_3 = Pin('P2_3') # GPIO0_23 - GPIO_23
|
||||
P2_4 = Pin('P2_4') # GPIO1_26 - GPIO_58
|
||||
P2_5 = Pin('P2_5') # UART4_RXD - GPIO_30
|
||||
P2_6 = Pin('P2_6') # GPIO1_25 - GPIO_57
|
||||
P2_7 = Pin('P2_7') # UART4_TXD - GPIO_31
|
||||
P2_8 = Pin('P2_8') # GPIO1_28 - GPIO_60
|
||||
P2_9 = Pin('P2_9') # I2C1_SCL - GPIO_15
|
||||
P2_10 = Pin('P2_10') # GPIO1_20 - GPIO_52
|
||||
P2_11 = Pin('P2_11') # I2C1_SDA - GPIO_14
|
||||
P2_1 = Pin("P2_1") # EHRPWM1A - GPIO_50
|
||||
P2_2 = Pin("P2_2") # GPIO1_27 - GPIO_59
|
||||
P2_3 = Pin("P2_3") # GPIO0_23 - GPIO_23
|
||||
P2_4 = Pin("P2_4") # GPIO1_26 - GPIO_58
|
||||
P2_5 = Pin("P2_5") # UART4_RXD - GPIO_30
|
||||
P2_6 = Pin("P2_6") # GPIO1_25 - GPIO_57
|
||||
P2_7 = Pin("P2_7") # UART4_TXD - GPIO_31
|
||||
P2_8 = Pin("P2_8") # GPIO1_28 - GPIO_60
|
||||
P2_9 = Pin("P2_9") # I2C1_SCL - GPIO_15
|
||||
P2_10 = Pin("P2_10") # GPIO1_20 - GPIO_52
|
||||
P2_11 = Pin("P2_11") # I2C1_SDA - GPIO_14
|
||||
# P2_12 = SYS PWR BTN # POWER_BUTTON
|
||||
# P2_13 = SYS VOUT # VOUT-5V
|
||||
# P2_14 = BAT VIN # BAT-VIN
|
||||
# P2_15 = SYS GND # GND
|
||||
# P2_16 = BAT TEMP # BAT-TEMP
|
||||
P2_17 = Pin('P2_17') # GPIO2_1 - GPIO_65
|
||||
P2_18 = Pin('P2_18') # GPIO1_15 - GPIO_47
|
||||
P2_19 = Pin('P2_19') # GPIO0_27 - GPIO_27
|
||||
P2_20 = Pin('P2_20') # GPIO2_0 - GPIO_64
|
||||
P2_17 = Pin("P2_17") # GPIO2_1 - GPIO_65
|
||||
P2_18 = Pin("P2_18") # GPIO1_15 - GPIO_47
|
||||
P2_19 = Pin("P2_19") # GPIO0_27 - GPIO_27
|
||||
P2_20 = Pin("P2_20") # GPIO2_0 - GPIO_64
|
||||
# P2_21 = SYS GND # GND
|
||||
P2_22 = Pin('P2_22') # GPIO1_14 - GPIO_46
|
||||
P2_22 = Pin("P2_22") # GPIO1_14 - GPIO_46
|
||||
# P2_23 = SYS 3.3V # VOUT-3.3V
|
||||
P2_24 = Pin('P2_24') # GPIO1_12 - GPIO_44
|
||||
P2_25 = Pin('P2_25') # SPI1_D1 - GPIO_41
|
||||
P2_24 = Pin("P2_24") # GPIO1_12 - GPIO_44
|
||||
P2_25 = Pin("P2_25") # SPI1_D1 - GPIO_41
|
||||
# P2_26 = SYS NRST # RESET#
|
||||
P2_27 = Pin('P2_27') # SPI1_D0 - GPIO_40
|
||||
P2_28 = Pin('P2_28') # GPIO3_20 - GPIO_116
|
||||
P2_29 = Pin('P2_29') # SPI1_SCLK - GPIO_7
|
||||
P2_30 = Pin('P2_30') # GPIO3_17 - GPIO_113
|
||||
P2_31 = Pin('P2_31') # SPI1_CS1 - GPIO_19
|
||||
P2_32 = Pin('P2_32') # GPIO3_16 - GPIO_112
|
||||
P2_33 = Pin('P2_33') # GPIO1_13 - GPIO_45
|
||||
P2_34 = Pin('P2_34') # GPIO3_19 - GPIO_115
|
||||
P2_35 = Pin('P2_35') # GPIO2_22 - GPIO_86
|
||||
P2_36 = Pin('P2_36') # AIN7
|
||||
P2_27 = Pin("P2_27") # SPI1_D0 - GPIO_40
|
||||
P2_28 = Pin("P2_28") # GPIO3_20 - GPIO_116
|
||||
P2_29 = Pin("P2_29") # SPI1_SCLK - GPIO_7
|
||||
P2_30 = Pin("P2_30") # GPIO3_17 - GPIO_113
|
||||
P2_31 = Pin("P2_31") # SPI1_CS1 - GPIO_19
|
||||
P2_32 = Pin("P2_32") # GPIO3_16 - GPIO_112
|
||||
P2_33 = Pin("P2_33") # GPIO1_13 - GPIO_45
|
||||
P2_34 = Pin("P2_34") # GPIO3_19 - GPIO_115
|
||||
P2_35 = Pin("P2_35") # GPIO2_22 - GPIO_86
|
||||
P2_36 = Pin("P2_36") # AIN7
|
||||
|
||||
|
||||
# BeagleBone Black
|
||||
# P8_1 = DGND # DGND - GPIO_0
|
||||
# P8_2 = DGND # DGND - GPIO_0
|
||||
P8_3 = Pin('P8_3') # GPIO1_6 - GPIO_38
|
||||
P8_4 = Pin('P8_4') # GPIO1_7 - GPIO_39
|
||||
P8_5 = Pin('P8_5') # GPIO1_2 - GPIO_34
|
||||
P8_6 = Pin('P8_6') # GPIO1_3 - GPIO_35
|
||||
P8_7 = Pin('P8_7') # TIMER4 - GPIO_66
|
||||
P8_8 = Pin('P8_8') # TIMER7 - GPIO_67
|
||||
P8_9 = Pin('P8_9') # TIMER5 - GPIO_69
|
||||
P8_10 = Pin('P8_10') # TIMER6 - GPIO_68
|
||||
P8_11 = Pin('P8_11') # GPIO1_13 - GPIO_45
|
||||
P8_12 = Pin('P8_12') # GPIO1_12 - GPIO_44
|
||||
P8_13 = Pin('P8_13') # EHRPWM2B - GPIO_23
|
||||
P8_14 = Pin('P8_14') # GPIO0_26 - GPIO_26
|
||||
P8_15 = Pin('P8_15') # GPIO1_15 - GPIO_47
|
||||
P8_16 = Pin('P8_16') # GPIO1_14 - GPIO_46
|
||||
P8_17 = Pin('P8_17') # GPIO0_27 - GPIO_27
|
||||
P8_18 = Pin('P8_18') # GPIO2_1 - GPIO_65
|
||||
P8_19 = Pin('P8_19') # EHRPWM2A - GPIO_22
|
||||
P8_20 = Pin('P8_20') # GPIO1_31 - GPIO_63
|
||||
P8_21 = Pin('P8_21') # GPIO1_30 - GPIO_62
|
||||
P8_22 = Pin('P8_22') # GPIO1_5 - GPIO_37
|
||||
P8_23 = Pin('P8_23') # GPIO1_4 - GPIO_36
|
||||
P8_24 = Pin('P8_24') # GPIO1_1 - GPIO_33
|
||||
P8_25 = Pin('P8_25') # GPIO1_0 - GPIO_32
|
||||
P8_26 = Pin('P8_26') # GPIO1_29 - GPIO_61
|
||||
P8_27 = Pin('P8_27') # GPIO2_22 - GPIO_86
|
||||
P8_28 = Pin('P8_28') # GPIO2_24 - GPIO_88
|
||||
P8_29 = Pin('P8_29') # GPIO2_23 - GPIO_87
|
||||
P8_30 = Pin('P8_30') # GPIO2_25 - GPIO_89
|
||||
P8_31 = Pin('P8_31') # UART5_CTSN - GPIO_10
|
||||
P8_32 = Pin('P8_32') # UART5_RTSN - GPIO_11
|
||||
P8_33 = Pin('P8_33') # UART4_RTSN - GPIO_9
|
||||
P8_34 = Pin('P8_34') # UART3_RTSN - GPIO_81
|
||||
P8_35 = Pin('P8_35') # UART4_CTSN - GPIO_8
|
||||
P8_36 = Pin('P8_36') # UART3_CTSN - GPIO_80
|
||||
P8_37 = Pin('P8_37') # UART5_TXD - GPIO_78
|
||||
P8_38 = Pin('P8_38') # UART5_RXD - GPIO_79
|
||||
P8_39 = Pin('P8_39') # GPIO2_12 - GPIO_76
|
||||
P8_40 = Pin('P8_40') # GPIO2_13 - GPIO_77
|
||||
P8_41 = Pin('P8_41') # GPIO2_10 - GPIO_74
|
||||
P8_42 = Pin('P8_42') # GPIO2_11 - GPIO_75
|
||||
P8_43 = Pin('P8_43') # GPIO2_8 - GPIO_72
|
||||
P8_44 = Pin('P8_44') # GPIO2_9 - GPIO_73
|
||||
P8_45 = Pin('P8_45') # GPIO2_6 - GPIO_70
|
||||
P8_46 = Pin('P8_46') # GPIO2_7 - GPIO_71
|
||||
P8_3 = Pin("P8_3") # GPIO1_6 - GPIO_38
|
||||
P8_4 = Pin("P8_4") # GPIO1_7 - GPIO_39
|
||||
P8_5 = Pin("P8_5") # GPIO1_2 - GPIO_34
|
||||
P8_6 = Pin("P8_6") # GPIO1_3 - GPIO_35
|
||||
P8_7 = Pin("P8_7") # TIMER4 - GPIO_66
|
||||
P8_8 = Pin("P8_8") # TIMER7 - GPIO_67
|
||||
P8_9 = Pin("P8_9") # TIMER5 - GPIO_69
|
||||
P8_10 = Pin("P8_10") # TIMER6 - GPIO_68
|
||||
P8_11 = Pin("P8_11") # GPIO1_13 - GPIO_45
|
||||
P8_12 = Pin("P8_12") # GPIO1_12 - GPIO_44
|
||||
P8_13 = Pin("P8_13") # EHRPWM2B - GPIO_23
|
||||
P8_14 = Pin("P8_14") # GPIO0_26 - GPIO_26
|
||||
P8_15 = Pin("P8_15") # GPIO1_15 - GPIO_47
|
||||
P8_16 = Pin("P8_16") # GPIO1_14 - GPIO_46
|
||||
P8_17 = Pin("P8_17") # GPIO0_27 - GPIO_27
|
||||
P8_18 = Pin("P8_18") # GPIO2_1 - GPIO_65
|
||||
P8_19 = Pin("P8_19") # EHRPWM2A - GPIO_22
|
||||
P8_20 = Pin("P8_20") # GPIO1_31 - GPIO_63
|
||||
P8_21 = Pin("P8_21") # GPIO1_30 - GPIO_62
|
||||
P8_22 = Pin("P8_22") # GPIO1_5 - GPIO_37
|
||||
P8_23 = Pin("P8_23") # GPIO1_4 - GPIO_36
|
||||
P8_24 = Pin("P8_24") # GPIO1_1 - GPIO_33
|
||||
P8_25 = Pin("P8_25") # GPIO1_0 - GPIO_32
|
||||
P8_26 = Pin("P8_26") # GPIO1_29 - GPIO_61
|
||||
P8_27 = Pin("P8_27") # GPIO2_22 - GPIO_86
|
||||
P8_28 = Pin("P8_28") # GPIO2_24 - GPIO_88
|
||||
P8_29 = Pin("P8_29") # GPIO2_23 - GPIO_87
|
||||
P8_30 = Pin("P8_30") # GPIO2_25 - GPIO_89
|
||||
P8_31 = Pin("P8_31") # UART5_CTSN - GPIO_10
|
||||
P8_32 = Pin("P8_32") # UART5_RTSN - GPIO_11
|
||||
P8_33 = Pin("P8_33") # UART4_RTSN - GPIO_9
|
||||
P8_34 = Pin("P8_34") # UART3_RTSN - GPIO_81
|
||||
P8_35 = Pin("P8_35") # UART4_CTSN - GPIO_8
|
||||
P8_36 = Pin("P8_36") # UART3_CTSN - GPIO_80
|
||||
P8_37 = Pin("P8_37") # UART5_TXD - GPIO_78
|
||||
P8_38 = Pin("P8_38") # UART5_RXD - GPIO_79
|
||||
P8_39 = Pin("P8_39") # GPIO2_12 - GPIO_76
|
||||
P8_40 = Pin("P8_40") # GPIO2_13 - GPIO_77
|
||||
P8_41 = Pin("P8_41") # GPIO2_10 - GPIO_74
|
||||
P8_42 = Pin("P8_42") # GPIO2_11 - GPIO_75
|
||||
P8_43 = Pin("P8_43") # GPIO2_8 - GPIO_72
|
||||
P8_44 = Pin("P8_44") # GPIO2_9 - GPIO_73
|
||||
P8_45 = Pin("P8_45") # GPIO2_6 - GPIO_70
|
||||
P8_46 = Pin("P8_46") # GPIO2_7 - GPIO_71
|
||||
|
||||
# P9_1 = DGND # DGND - GPIO_0
|
||||
# P9_2 = DGND # DGND - GPIO_0
|
||||
|
|
@ -195,27 +200,27 @@ P8_46 = Pin('P8_46') # GPIO2_7 - GPIO_71
|
|||
# P9_8 = SYS_5V # SYS_5V - GPIO_0
|
||||
# P9_9 = PWR_BUT # PWR_BUT - GPIO_0
|
||||
# P9_10 = SYS_RESETN # SYS_RESETn - GPIO_0
|
||||
P9_11 = Pin('P9_11') # UART4_RXD - GPIO_30
|
||||
P9_12 = Pin('P9_12') # GPIO1_28 - GPIO_60
|
||||
P9_13 = Pin('P9_13') # UART4_TXD - GPIO_31
|
||||
P9_14 = Pin('P9_14') # EHRPWM1A - GPIO_50
|
||||
P9_15 = Pin('P9_15') # GPIO1_16 - GPIO_48
|
||||
P9_16 = Pin('P9_16') # EHRPWM1B - GPIO_51
|
||||
P9_17 = Pin('P9_17') # I2C1_SCL - GPIO_5
|
||||
P9_18 = Pin('P9_18') # I2C1_SDA - GPIO_4
|
||||
P9_19 = Pin('P9_19') # I2C2_SCL - GPIO_13
|
||||
P9_20 = Pin('P9_20') # I2C2_SDA - GPIO_12
|
||||
P9_21 = Pin('P9_21') # UART2_TXD - GPIO_3
|
||||
P9_22 = Pin('P9_22') # UART2_RXD - GPIO_2
|
||||
P9_23 = Pin('P9_23') # GPIO1_17 - GPIO_49
|
||||
P9_24 = Pin('P9_24') # UART1_TXD - GPIO_15
|
||||
P9_25 = Pin('P9_25') # GPIO3_21 - GPIO_117
|
||||
P9_26 = Pin('P9_26') # UART1_RXD - GPIO_14
|
||||
P9_27 = Pin('P9_27') # GPIO3_19 - GPIO_115
|
||||
P9_28 = Pin('P9_28') # SPI1_CS0 - GPIO_113
|
||||
P9_29 = Pin('P9_29') # SPI1_D0 - GPIO_111
|
||||
P9_30 = Pin('P9_30') # SPI1_D1 - GPIO_112
|
||||
P9_31 = Pin('P9_31') # SPI1_SCLK - GPIO_110
|
||||
P9_11 = Pin("P9_11") # UART4_RXD - GPIO_30
|
||||
P9_12 = Pin("P9_12") # GPIO1_28 - GPIO_60
|
||||
P9_13 = Pin("P9_13") # UART4_TXD - GPIO_31
|
||||
P9_14 = Pin("P9_14") # EHRPWM1A - GPIO_50
|
||||
P9_15 = Pin("P9_15") # GPIO1_16 - GPIO_48
|
||||
P9_16 = Pin("P9_16") # EHRPWM1B - GPIO_51
|
||||
P9_17 = Pin("P9_17") # I2C1_SCL - GPIO_5
|
||||
P9_18 = Pin("P9_18") # I2C1_SDA - GPIO_4
|
||||
P9_19 = Pin("P9_19") # I2C2_SCL - GPIO_13
|
||||
P9_20 = Pin("P9_20") # I2C2_SDA - GPIO_12
|
||||
P9_21 = Pin("P9_21") # UART2_TXD - GPIO_3
|
||||
P9_22 = Pin("P9_22") # UART2_RXD - GPIO_2
|
||||
P9_23 = Pin("P9_23") # GPIO1_17 - GPIO_49
|
||||
P9_24 = Pin("P9_24") # UART1_TXD - GPIO_15
|
||||
P9_25 = Pin("P9_25") # GPIO3_21 - GPIO_117
|
||||
P9_26 = Pin("P9_26") # UART1_RXD - GPIO_14
|
||||
P9_27 = Pin("P9_27") # GPIO3_19 - GPIO_115
|
||||
P9_28 = Pin("P9_28") # SPI1_CS0 - GPIO_113
|
||||
P9_29 = Pin("P9_29") # SPI1_D0 - GPIO_111
|
||||
P9_30 = Pin("P9_30") # SPI1_D1 - GPIO_112
|
||||
P9_31 = Pin("P9_31") # SPI1_SCLK - GPIO_110
|
||||
# P9_32 = VDD_ADC # VDD_ADC - GPIO_0
|
||||
# P9_33 = AIN4 # AIN4 - GPIO_0
|
||||
# P9_34 = GNDA_ADC # GNDA_ADC - GPIO_0
|
||||
|
|
@ -225,8 +230,8 @@ P9_31 = Pin('P9_31') # SPI1_SCLK - GPIO_110
|
|||
# P9_38 = AIN3 # AIN3 - GPIO_0
|
||||
# P9_39 = AIN0 # AIN0 - GPIO_0
|
||||
# P9_40 = AIN1 # AIN1 - GPIO_0
|
||||
P9_41 = Pin('P9_41') # CLKOUT2 - GPIO_20
|
||||
P9_42 = Pin('P9_42') # GPIO0_7 - GPIO_7
|
||||
P9_41 = Pin("P9_41") # CLKOUT2 - GPIO_20
|
||||
P9_42 = Pin("P9_42") # GPIO0_7 - GPIO_7
|
||||
# P9_43 = DGND # DGND - GPIO_0
|
||||
# P9_44 = DGND # DGND - GPIO_0
|
||||
# P9_45 = DGND # DGND - GPIO_0
|
||||
|
|
@ -235,92 +240,92 @@ P9_42 = Pin('P9_42') # GPIO0_7 - GPIO_7
|
|||
|
||||
##########################################
|
||||
# common to all beagles
|
||||
USR0 = Pin('USR0') # USR0 - GPIO_53
|
||||
USR1 = Pin('USR1') # USR1 - GPIO_54
|
||||
USR2 = Pin('USR2') # USR2 - GPIO_55
|
||||
USR3 = Pin('USR3') # USR3 - GPIO_56
|
||||
USR0 = Pin("USR0") # USR0 - GPIO_53
|
||||
USR1 = Pin("USR1") # USR1 - GPIO_54
|
||||
USR2 = Pin("USR2") # USR2 - GPIO_55
|
||||
USR3 = Pin("USR3") # USR3 - GPIO_56
|
||||
|
||||
|
||||
##########################################
|
||||
# specials
|
||||
|
||||
# analog input
|
||||
AIN0 = Pin('AIN0')
|
||||
AIN1 = Pin('AIN1')
|
||||
AIN2 = Pin('AIN2')
|
||||
AIN3 = Pin('AIN3')
|
||||
AIN4 = Pin('AIN4')
|
||||
AIN5 = Pin('AIN5')
|
||||
AIN6 = Pin('AIN6')
|
||||
AIN7 = Pin('AIN7')
|
||||
AIN0 = Pin("AIN0")
|
||||
AIN1 = Pin("AIN1")
|
||||
AIN2 = Pin("AIN2")
|
||||
AIN3 = Pin("AIN3")
|
||||
AIN4 = Pin("AIN4")
|
||||
AIN5 = Pin("AIN5")
|
||||
AIN6 = Pin("AIN6")
|
||||
AIN7 = Pin("AIN7")
|
||||
|
||||
# PWM
|
||||
EHRPWM0A = Pin('EHRPWM0A')
|
||||
EHRPWM0B = Pin('EHRPWM0B')
|
||||
EHRPWM1A = Pin('EHRPWM1A')
|
||||
EHRPWM1B = Pin('EHRPWM1B')
|
||||
EHRPWM2A = Pin('EHRPWM2A')
|
||||
EHRPWM2B = Pin('EHRPWM2B')
|
||||
ECAPPWM0 = Pin('ECAPPWM0')
|
||||
ECAPPWM2 = Pin('ECAPPWM2')
|
||||
TIMER4 = Pin('TIMER4')
|
||||
TIMER5 = Pin('TIMER5')
|
||||
TIMER6 = Pin('TIMER6')
|
||||
TIMER7 = Pin('TIMER7')
|
||||
EHRPWM0A = Pin("EHRPWM0A")
|
||||
EHRPWM0B = Pin("EHRPWM0B")
|
||||
EHRPWM1A = Pin("EHRPWM1A")
|
||||
EHRPWM1B = Pin("EHRPWM1B")
|
||||
EHRPWM2A = Pin("EHRPWM2A")
|
||||
EHRPWM2B = Pin("EHRPWM2B")
|
||||
ECAPPWM0 = Pin("ECAPPWM0")
|
||||
ECAPPWM2 = Pin("ECAPPWM2")
|
||||
TIMER4 = Pin("TIMER4")
|
||||
TIMER5 = Pin("TIMER5")
|
||||
TIMER6 = Pin("TIMER6")
|
||||
TIMER7 = Pin("TIMER7")
|
||||
|
||||
|
||||
# I2C1
|
||||
I2C1_SDA = Pin('I2C1_SDA')
|
||||
I2C1_SCL = Pin('I2C1_SCL')
|
||||
I2C1_SDA = Pin("I2C1_SDA")
|
||||
I2C1_SCL = Pin("I2C1_SCL")
|
||||
|
||||
# I2C2
|
||||
I2C2_SDA = Pin('I2C2_SDA')
|
||||
I2C2_SCL = Pin('I2C2_SCL')
|
||||
I2C2_SDA = Pin("I2C2_SDA")
|
||||
I2C2_SCL = Pin("I2C2_SCL")
|
||||
|
||||
# SPI0
|
||||
SPI0_CS0 = Pin('SPI0_CS0')
|
||||
SPI0_SCLK = Pin('SPI0_SCLK')
|
||||
SPI0_D1 = Pin('SPI0_D1')
|
||||
SPI0_D0 = Pin('SPI0_D0')
|
||||
SPI0_CS0 = Pin("SPI0_CS0")
|
||||
SPI0_SCLK = Pin("SPI0_SCLK")
|
||||
SPI0_D1 = Pin("SPI0_D1")
|
||||
SPI0_D0 = Pin("SPI0_D0")
|
||||
|
||||
# SPI1
|
||||
SPI1_CS0 = Pin('SPI1_CS0')
|
||||
SPI1_CS1 = Pin('SPI1_CS1')
|
||||
SPI1_SCLK = Pin('SPI1_SCLK')
|
||||
SPI1_D1 = Pin('SPI1_D1')
|
||||
SPI1_D0 = Pin('SPI1_D0')
|
||||
SPI1_CS0 = Pin("SPI1_CS0")
|
||||
SPI1_CS1 = Pin("SPI1_CS1")
|
||||
SPI1_SCLK = Pin("SPI1_SCLK")
|
||||
SPI1_D1 = Pin("SPI1_D1")
|
||||
SPI1_D0 = Pin("SPI1_D0")
|
||||
|
||||
# UART0
|
||||
UART0_TXD = Pin('UART0_TXD')
|
||||
UART0_RXD = Pin('UART0_RXD')
|
||||
UART0_TXD = Pin("UART0_TXD")
|
||||
UART0_RXD = Pin("UART0_RXD")
|
||||
|
||||
# UART1
|
||||
UART1_TXD = Pin('UART1_TXD')
|
||||
UART1_RXD = Pin('UART1_RXD')
|
||||
UART1_RTSn = Pin('UART1_RTSn')
|
||||
UART1_CTSn = Pin('UART1_CTSn')
|
||||
UART1_TXD = Pin("UART1_TXD")
|
||||
UART1_RXD = Pin("UART1_RXD")
|
||||
UART1_RTSn = Pin("UART1_RTSn")
|
||||
UART1_CTSn = Pin("UART1_CTSn")
|
||||
|
||||
# UART2
|
||||
UART2_TXD = Pin('UART2_TXD')
|
||||
UART2_RXD = Pin('UART2_RXD')
|
||||
UART2_TXD = Pin("UART2_TXD")
|
||||
UART2_RXD = Pin("UART2_RXD")
|
||||
|
||||
# UART3
|
||||
UART3_TXD = Pin('UART3_TXD')
|
||||
UART3_RXD = Pin('UART3_RXD')
|
||||
UART3_RTSn = Pin('UART3_RTSn')
|
||||
UART3_CTSn = Pin('UART3_CTSn')
|
||||
UART3_TXD = Pin("UART3_TXD")
|
||||
UART3_RXD = Pin("UART3_RXD")
|
||||
UART3_RTSn = Pin("UART3_RTSn")
|
||||
UART3_CTSn = Pin("UART3_CTSn")
|
||||
|
||||
# UART4
|
||||
UART4_TXD = Pin('UART4_TXD')
|
||||
UART4_RXD = Pin('UART4_RXD')
|
||||
UART4_RTSn = Pin('UART4_RTSn')
|
||||
UART4_CTSn = Pin('UART4_CTSn')
|
||||
UART4_TXD = Pin("UART4_TXD")
|
||||
UART4_RXD = Pin("UART4_RXD")
|
||||
UART4_RTSn = Pin("UART4_RTSn")
|
||||
UART4_CTSn = Pin("UART4_CTSn")
|
||||
|
||||
# UART5
|
||||
UART5_TXD = Pin('UART5_TXD')
|
||||
UART5_RXD = Pin('UART5_RXD')
|
||||
UART5_RTSn = Pin('UART5_RTSn')
|
||||
UART5_CTSn = Pin('UART5_CTSn')
|
||||
UART5_TXD = Pin("UART5_TXD")
|
||||
UART5_RXD = Pin("UART5_RXD")
|
||||
UART5_RTSn = Pin("UART5_RTSn")
|
||||
UART5_CTSn = Pin("UART5_CTSn")
|
||||
|
||||
|
||||
# ordered as spiId, sckId, mosiId, misoId
|
||||
|
|
|
|||
|
|
@ -1,21 +1,29 @@
|
|||
# Much code from https://github.com/vsergeev/python-periphery/blob/master/periphery/pwm.py
|
||||
# Copyright (c) 2015-2016 vsergeev / Ivan (Vanya) A. Sergeev
|
||||
# License: MIT
|
||||
"""
|
||||
Much code from https://github.com/vsergeev/python-periphery/blob/master/periphery/pwm.py
|
||||
Copyright (c) 2015-2016 vsergeev / Ivan (Vanya) A. Sergeev
|
||||
License: MIT
|
||||
"""
|
||||
|
||||
import os
|
||||
import digitalio
|
||||
|
||||
try:
|
||||
from microcontroller.pin import pwmOuts
|
||||
except ImportError:
|
||||
raise RuntimeError("No PWM outputs defined for this board")
|
||||
|
||||
# pylint: disable=unnecessary-pass
|
||||
class PWMError(IOError):
|
||||
"""Base class for PWM errors."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class PWMOut(object):
|
||||
# pylint: enable=unnecessary-pass
|
||||
|
||||
|
||||
class PWMOut:
|
||||
"""Pulse Width Modulation Output Class"""
|
||||
|
||||
# Sysfs paths
|
||||
_sysfs_path = "/sys/class/pwm/"
|
||||
_channel_path = "pwmchip{}"
|
||||
|
|
@ -52,6 +60,8 @@ class PWMOut(object):
|
|||
"""
|
||||
|
||||
self._pwmpin = None
|
||||
self._channel = None
|
||||
self._period = 0
|
||||
self._open(pin, duty_cycle, frequency, variable_frequency)
|
||||
|
||||
def __del__(self):
|
||||
|
|
@ -74,14 +84,22 @@ class PWMOut(object):
|
|||
if self._channel is None:
|
||||
raise RuntimeError("No PWM channel found for this Pin")
|
||||
|
||||
channel_path = os.path.join(self._sysfs_path, self._channel_path.format(self._channel))
|
||||
channel_path = os.path.join(
|
||||
self._sysfs_path, self._channel_path.format(self._channel)
|
||||
)
|
||||
if not os.path.isdir(channel_path):
|
||||
raise ValueError("PWM channel does not exist, check that the required modules are loaded.")
|
||||
raise ValueError(
|
||||
"PWM channel does not exist, check that the required modules are loaded."
|
||||
)
|
||||
|
||||
pin_path = os.path.join(channel_path, self._pin_path.format(self._channel,self._pwmpin))
|
||||
pin_path = os.path.join(
|
||||
channel_path, self._pin_path.format(self._channel, self._pwmpin)
|
||||
)
|
||||
if not os.path.isdir(pin_path):
|
||||
try:
|
||||
with open(os.path.join(channel_path, self._export_path), "w") as f_export:
|
||||
with open(
|
||||
os.path.join(channel_path, self._export_path), "w"
|
||||
) as f_export:
|
||||
f_export.write("%d\n" % self._pwmpin)
|
||||
except IOError as e:
|
||||
raise PWMError(e.errno, "Exporting PWM pin: " + e.strerror)
|
||||
|
|
@ -97,17 +115,24 @@ class PWMOut(object):
|
|||
self._set_enabled(True)
|
||||
|
||||
def deinit(self):
|
||||
try:
|
||||
"""Deinit the sysfs PWM."""
|
||||
channel_path = os.path.join(self._sysfs_path, self._channel_path.format(self._channel))
|
||||
pin_path = os.path.join(channel_path, self._pin_path.format(self._channel,self._pwmpin))
|
||||
# pylint: disable=broad-except
|
||||
try:
|
||||
channel_path = os.path.join(
|
||||
self._sysfs_path, self._channel_path.format(self._channel)
|
||||
)
|
||||
pin_path = os.path.join(
|
||||
channel_path, self._pin_path.format(self._channel, self._pwmpin)
|
||||
)
|
||||
|
||||
if self._channel is not None:
|
||||
# self.duty_cycle = 0
|
||||
self._set_enabled(False) # make to disable before unexport
|
||||
try:
|
||||
# unexport_path = os.path.join(channel_path, self._unexport_path)
|
||||
with open(os.path.join(channel_path, self._unexport_path), "w") as f_unexport:
|
||||
with open(
|
||||
os.path.join(channel_path, self._unexport_path), "w"
|
||||
) as f_unexport:
|
||||
f_unexport.write("%d\n" % self._pwmpin)
|
||||
except IOError as e:
|
||||
raise PWMError(e.errno, "Unexporting PWM pin: " + e.strerror)
|
||||
|
|
@ -115,15 +140,22 @@ class PWMOut(object):
|
|||
# due to a race condition for which I have not yet been
|
||||
# able to find the root cause, deinit() often fails
|
||||
# but it does not effect future usage of the pwm pin
|
||||
print("warning: failed to deinitialize pwm pin {0}:{1} due to: {2}\n".format(self._channel, self._pwmpin, type(e).__name__))
|
||||
print(
|
||||
"warning: failed to deinitialize pwm pin {0}:{1} due to: {2}\n".format(
|
||||
self._channel, self._pwmpin, type(e).__name__
|
||||
)
|
||||
)
|
||||
finally:
|
||||
self._channel = None
|
||||
self._pwmpin = None
|
||||
# pylint: enable=broad-except
|
||||
|
||||
def _is_deinited(self):
|
||||
if self._pwmpin is None:
|
||||
raise ValueError("Object has been deinitialize and can no longer "
|
||||
"be used. Create a new object.")
|
||||
raise ValueError(
|
||||
"Object has been deinitialize and can no longer "
|
||||
"be used. Create a new object."
|
||||
)
|
||||
|
||||
def _write_pin_attr(self, attr, value):
|
||||
# Make sure the pin is active
|
||||
|
|
@ -133,9 +165,10 @@ class PWMOut(object):
|
|||
self._sysfs_path,
|
||||
self._channel_path.format(self._channel),
|
||||
self._pin_path.format(self._channel, self._pwmpin),
|
||||
attr)
|
||||
attr,
|
||||
)
|
||||
|
||||
with open(path, 'w') as f_attr:
|
||||
with open(path, "w") as f_attr:
|
||||
f_attr.write(value + "\n")
|
||||
|
||||
def _read_pin_attr(self, attr):
|
||||
|
|
@ -146,9 +179,10 @@ class PWMOut(object):
|
|||
self._sysfs_path,
|
||||
self._channel_path.format(self._channel),
|
||||
self._pin_path.format(self._channel, self._pwmpin),
|
||||
attr)
|
||||
attr,
|
||||
)
|
||||
|
||||
with open(path, 'r') as f_attr:
|
||||
with open(path, "r") as f_attr:
|
||||
return f_attr.read().strip()
|
||||
|
||||
# Mutable properties
|
||||
|
|
@ -158,7 +192,7 @@ class PWMOut(object):
|
|||
try:
|
||||
period_ns = int(period_ns)
|
||||
except ValueError:
|
||||
raise PWMError(None, "Unknown period value: \"%s\"" % period_ns)
|
||||
raise PWMError(None, 'Unknown period value: "%s"' % period_ns)
|
||||
|
||||
# Convert period from nanoseconds to seconds
|
||||
period = period_ns / 1e9
|
||||
|
|
@ -196,7 +230,7 @@ class PWMOut(object):
|
|||
try:
|
||||
duty_cycle_ns = int(duty_cycle_ns)
|
||||
except ValueError:
|
||||
raise PWMError(None, "Unknown duty cycle value: \"%s\"" % duty_cycle_ns)
|
||||
raise PWMError(None, 'Unknown duty cycle value: "%s"' % duty_cycle_ns)
|
||||
|
||||
# Convert duty cycle from nanoseconds to seconds
|
||||
duty_cycle = duty_cycle_ns / 1e9
|
||||
|
|
@ -260,17 +294,12 @@ class PWMOut(object):
|
|||
|
||||
if enabled == "1":
|
||||
return True
|
||||
elif enabled == "0":
|
||||
if enabled == "0":
|
||||
return False
|
||||
|
||||
raise PWMError(None, "Unknown enabled value: \"%s\"" % enabled)
|
||||
raise PWMError(None, 'Unknown enabled value: "%s"' % enabled)
|
||||
|
||||
def _set_enabled(self, value):
|
||||
if not isinstance(value, bool):
|
||||
raise TypeError("Invalid enabled type, should be string.")
|
||||
|
||||
self._write_pin_attr(self._pin_enable_path, "1" if value else "0")
|
||||
|
||||
"""Get or set the PWM's output enabled state.
|
||||
|
||||
Raises:
|
||||
|
|
@ -279,9 +308,17 @@ class PWMOut(object):
|
|||
|
||||
:type: bool
|
||||
"""
|
||||
if not isinstance(value, bool):
|
||||
raise TypeError("Invalid enabled type, should be string.")
|
||||
|
||||
self._write_pin_attr(self._pin_enable_path, "1" if value else "0")
|
||||
|
||||
# String representation
|
||||
|
||||
def __str__(self):
|
||||
return "PWM%d, pin %s (freq=%f Hz, duty_cycle=%f%%)" % \
|
||||
(self._channel, self._pin, self.frequency, self.duty_cycle * 100,)
|
||||
return "PWM%d, pin %s (freq=%f Hz, duty_cycle=%f%%)" % (
|
||||
self._channel,
|
||||
self._pin,
|
||||
self.frequency,
|
||||
self.duty_cycle * 100,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
"""
|
||||
G12A, G12B, and SM1 Common Definitions
|
||||
Ref:
|
||||
Linux kernel 4.9.y (hardkernel)
|
||||
linux/include/dt-bindings/gpio/meson-g12a-gpio.h
|
||||
Linux kernel 5.4.y (mainline)
|
||||
linux/include/dt-bindings/gpio/meson-g12a-gpio.h
|
||||
linux/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
|
||||
"""
|
||||
|
||||
import re
|
||||
from adafruit_blinka.microcontroller.generic_linux.libgpiod_pin import Pin
|
||||
import gpiod
|
||||
import re
|
||||
|
||||
# G12A, G12B, and SM1
|
||||
# Ref:
|
||||
# Linux kernel 4.9.y (hardkernel)
|
||||
# linux/include/dt-bindings/gpio/meson-g12a-gpio.h
|
||||
# Linux kernel 5.4.y (mainline)
|
||||
# linux/include/dt-bindings/gpio/meson-g12a-gpio.h
|
||||
# linux/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
|
||||
|
||||
chip0 = gpiod.Chip("0")
|
||||
chip1 = gpiod.Chip("1")
|
||||
|
|
@ -106,10 +108,11 @@ uartPorts = ((1, UART1_TX, UART1_RX), )
|
|||
|
||||
|
||||
def get_dts_alias(device: str) -> str:
|
||||
"""Get the Device Tree Alias"""
|
||||
uevent_path = "/sys/bus/platform/devices/" + device + "/uevent"
|
||||
with open(uevent_path, 'r') as fd:
|
||||
with open(uevent_path, "r") as fd:
|
||||
pattern = r"^OF_ALIAS_0=(.*)$"
|
||||
uevent = fd.read().split('\n')
|
||||
uevent = fd.read().split("\n")
|
||||
for line in uevent:
|
||||
match = re.search(pattern, line)
|
||||
if match:
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
"""AmLogic s905 pin names"""
|
||||
from adafruit_blinka.microcontroller.generic_linux.libgpiod_pin import Pin
|
||||
|
||||
GPIO122 = Pin((0, 0))
|
||||
|
|
@ -76,8 +77,14 @@ SPI0_SCLK = GPIO230
|
|||
SPI0_MISO = GPIO232
|
||||
SPI0_MOSI = GPIO235
|
||||
|
||||
i2cPorts = ( (0, I2C0_SCL, I2C0_SDA), (1, I2C1_SCL, I2C1_SDA), )
|
||||
i2cPorts = (
|
||||
(0, I2C0_SCL, I2C0_SDA),
|
||||
(1, I2C1_SCL, I2C1_SDA),
|
||||
)
|
||||
# ordered as spiId, sckId, mosiId, misoId
|
||||
spiPorts = ((0, SPI0_SCLK, SPI0_MOSI, SPI0_MISO),)
|
||||
# ordered as uartId, txId, rxId
|
||||
uartPorts = ( (1, UART1_TX, UART1_RX), (2, UART2_TX, UART2_RX), )
|
||||
uartPorts = (
|
||||
(1, UART1_TX, UART1_RX),
|
||||
(2, UART2_TX, UART2_RX),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1 +1,3 @@
|
|||
"""AmLogic s905x3 pin names"""
|
||||
# pylint: disable=wildcard-import,unused-wildcard-import
|
||||
from adafruit_blinka.microcontroller.amlogic.meson_g12_common.pin import *
|
||||
|
|
|
|||
|
|
@ -1 +1,3 @@
|
|||
"""AmLogic s922x pin names"""
|
||||
# pylint: disable=wildcard-import,unused-wildcard-import
|
||||
from adafruit_blinka.microcontroller.amlogic.meson_g12_common.pin import *
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
"""Atheros AR9331 pin names"""
|
||||
from adafruit_blinka.microcontroller.generic_linux.libgpiod_pin import Pin
|
||||
|
||||
GPIO_0 = Pin((0, 0))
|
||||
|
|
@ -39,17 +40,10 @@ GPIO_27 = Pin((0, 27))
|
|||
GPIO_28 = Pin((0, 28))
|
||||
|
||||
# ordered as i2cId, sclId, sdaId
|
||||
i2cPorts = (
|
||||
(0, TWI0_SCL, TWI0_SDA)
|
||||
)
|
||||
i2cPorts = (0, TWI0_SCL, TWI0_SDA)
|
||||
|
||||
# ordered as spiId, sckId, mosiId, misoId
|
||||
spiPorts = (
|
||||
(1, SPI_CLK, SPI_MOSI, SPI_MISO),
|
||||
)
|
||||
spiPorts = ((1, SPI_CLK, SPI_MOSI, SPI_MISO),)
|
||||
|
||||
# ordered as uartId, txId, rxId
|
||||
uartPorts = (
|
||||
(0, UART0_TX, UART0_RX)
|
||||
)
|
||||
|
||||
uartPorts = (0, UART0_TX, UART0_RX)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
"""BCM283x NeoPixel Driver Class"""
|
||||
import time
|
||||
import math
|
||||
import _rpi_ws281x as ws
|
||||
import atexit
|
||||
import _rpi_ws281x as ws
|
||||
|
||||
# LED configuration.
|
||||
# pylint: disable=redefined-outer-name,too-many-branches,too-many-statements
|
||||
# pylint: disable=global-statement,protected-access
|
||||
LED_CHANNEL = 0
|
||||
LED_FREQ_HZ = 800000 # Frequency of the LED signal. We only support 800KHz
|
||||
LED_DMA_NUM = 10 # DMA channel to use, can be 0-14.
|
||||
|
|
@ -15,7 +17,9 @@ LED_STRIP = None # We manage the color order within the neopixel library
|
|||
# we only support one LED strip per raspi
|
||||
_led_strip = None
|
||||
|
||||
|
||||
def neopixel_write(gpio, buf):
|
||||
"""NeoPixel Writing Function"""
|
||||
global _led_strip # we'll have one strip we init if its not at first
|
||||
|
||||
if _led_strip is None:
|
||||
|
|
@ -47,7 +51,9 @@ def neopixel_write(gpio, buf):
|
|||
else:
|
||||
raise RuntimeError("We only support 3 or 4 bytes-per-pixel")
|
||||
|
||||
ws.ws2811_channel_t_count_set(channel, count) # we manage 4 vs 3 bytes in the library
|
||||
ws.ws2811_channel_t_count_set(
|
||||
channel, count
|
||||
) # we manage 4 vs 3 bytes in the library
|
||||
ws.ws2811_channel_t_gpionum_set(channel, gpio._pin.id)
|
||||
ws.ws2811_channel_t_invert_set(channel, LED_INVERT)
|
||||
ws.ws2811_channel_t_brightness_set(channel, LED_BRIGHTNESS)
|
||||
|
|
@ -60,9 +66,13 @@ def neopixel_write(gpio, buf):
|
|||
resp = ws.ws2811_init(_led_strip)
|
||||
if resp != ws.WS2811_SUCCESS:
|
||||
if resp == -5:
|
||||
raise RuntimeError("NeoPixel support requires running with sudo, please try again!")
|
||||
raise RuntimeError(
|
||||
"NeoPixel support requires running with sudo, please try again!"
|
||||
)
|
||||
message = ws.ws2811_get_return_t_str(resp)
|
||||
raise RuntimeError('ws2811_init failed with code {0} ({1})'.format(resp, message))
|
||||
raise RuntimeError(
|
||||
"ws2811_init failed with code {0} ({1})".format(resp, message)
|
||||
)
|
||||
atexit.register(neopixel_cleanup)
|
||||
|
||||
channel = ws.ws2811_channel_get(_led_strip, LED_CHANNEL)
|
||||
|
|
@ -88,11 +98,14 @@ def neopixel_write(gpio, buf):
|
|||
resp = ws.ws2811_render(_led_strip)
|
||||
if resp != ws.WS2811_SUCCESS:
|
||||
message = ws.ws2811_get_return_t_str(resp)
|
||||
raise RuntimeError('ws2811_render failed with code {0} ({1})'.format(resp, message))
|
||||
raise RuntimeError(
|
||||
"ws2811_render failed with code {0} ({1})".format(resp, message)
|
||||
)
|
||||
time.sleep(0.001 * ((len(buf) // 100) + 1)) # about 1ms per 100 bytes
|
||||
|
||||
|
||||
def neopixel_cleanup():
|
||||
"""Cleanup when we're done"""
|
||||
global _led_strip
|
||||
|
||||
if _led_strip is not None:
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
"""Broadcom BCM283x pin names"""
|
||||
import RPi.GPIO as GPIO
|
||||
|
||||
GPIO.setmode(GPIO.BCM) # Use BCM pins D4 = GPIO #4
|
||||
GPIO.setwarnings(False) # shh!
|
||||
|
||||
# Pins dont exist in CPython so...lets make our own!
|
||||
|
||||
class Pin:
|
||||
"""Pins dont exist in CPython so...lets make our own!"""
|
||||
|
||||
IN = 0
|
||||
OUT = 1
|
||||
LOW = 0
|
||||
|
|
@ -26,7 +30,8 @@ class Pin:
|
|||
return self.id == other
|
||||
|
||||
def init(self, mode=IN, pull=None):
|
||||
if mode != None:
|
||||
"""Initialize the Pin"""
|
||||
if mode is not None:
|
||||
if mode == self.IN:
|
||||
self._mode = self.IN
|
||||
GPIO.setup(self.id, GPIO.IN)
|
||||
|
|
@ -35,7 +40,7 @@ class Pin:
|
|||
GPIO.setup(self.id, GPIO.OUT)
|
||||
else:
|
||||
raise RuntimeError("Invalid mode for pin: %s" % self.id)
|
||||
if pull != None:
|
||||
if pull is not None:
|
||||
if self._mode != self.IN:
|
||||
raise RuntimeError("Cannot set pull resistor on output")
|
||||
if pull == self.PULL_UP:
|
||||
|
|
@ -46,7 +51,8 @@ class Pin:
|
|||
raise RuntimeError("Invalid pull for pin: %s" % self.id)
|
||||
|
||||
def value(self, val=None):
|
||||
if val != None:
|
||||
"""Set or return the Pin Value"""
|
||||
if val is not None:
|
||||
if val == self.LOW:
|
||||
self._value = val
|
||||
GPIO.output(self.id, val)
|
||||
|
|
@ -55,9 +61,10 @@ class Pin:
|
|||
GPIO.output(self.id, val)
|
||||
else:
|
||||
raise RuntimeError("Invalid value for pin")
|
||||
else:
|
||||
return None
|
||||
return GPIO.input(self.id)
|
||||
|
||||
|
||||
# Pi 1B rev1 only?
|
||||
D0 = Pin(0)
|
||||
D1 = Pin(1)
|
||||
|
|
@ -131,13 +138,17 @@ D44 = Pin(44)
|
|||
D45 = Pin(45)
|
||||
|
||||
# ordered as spiId, sckId, mosiId, misoId
|
||||
spiPorts = ((0, SCLK, MOSI, MISO), (1, SCLK_1, MOSI_1, MISO_1), (2, SCLK_2, MOSI_2, MISO_2))
|
||||
spiPorts = (
|
||||
(0, SCLK, MOSI, MISO),
|
||||
(1, SCLK_1, MOSI_1, MISO_1),
|
||||
(2, SCLK_2, MOSI_2, MISO_2),
|
||||
)
|
||||
|
||||
# ordered as uartId, txId, rxId
|
||||
uartPorts = (
|
||||
(1, TXD, RXD),
|
||||
)
|
||||
uartPorts = ((1, TXD, RXD),)
|
||||
|
||||
i2cPorts = (
|
||||
(3, SCL, SDA), (1, SCL, SDA), (0, D1, D0), # both pi 1 and pi 2 i2c ports!
|
||||
(3, SCL, SDA),
|
||||
(1, SCL, SDA),
|
||||
(0, D1, D0), # both pi 1 and pi 2 i2c ports!
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
import array
|
||||
"""Custom PulseIn Class to read PWM signals"""
|
||||
import time
|
||||
import subprocess
|
||||
import os, signal
|
||||
import traceback
|
||||
import signal
|
||||
import sysv_ipc
|
||||
import os
|
||||
import atexit
|
||||
import random
|
||||
import sysv_ipc
|
||||
|
||||
DEBUG = False
|
||||
queues = []
|
||||
|
|
@ -23,9 +21,14 @@ def final():
|
|||
q.remove()
|
||||
for proc in procs:
|
||||
proc.terminate()
|
||||
|
||||
|
||||
atexit.register(final)
|
||||
|
||||
# pylint: disable=c-extension-no-member
|
||||
class PulseIn:
|
||||
"""PulseIn Class to read PWM signals"""
|
||||
|
||||
def __init__(self, pin, maxlen=2, idle_state=False):
|
||||
"""Create a PulseIn object associated with the given pin.
|
||||
The object acts as a read-only sequence of pulse lengths with
|
||||
|
|
@ -45,9 +48,13 @@ class PulseIn:
|
|||
raise RuntimeError("Message queue creation failed")
|
||||
|
||||
dir_path = os.path.dirname(os.path.realpath(__file__))
|
||||
cmd = [dir_path+"/libgpiod_pulsein",
|
||||
"--pulses", str(maxlen),
|
||||
"--queue", str(self._mq.key)]
|
||||
cmd = [
|
||||
dir_path + "/libgpiod_pulsein",
|
||||
"--pulses",
|
||||
str(maxlen),
|
||||
"--queue",
|
||||
str(self._mq.key),
|
||||
]
|
||||
if idle_state:
|
||||
cmd.append("-i")
|
||||
cmd.append("gpiochip0")
|
||||
|
|
@ -62,23 +69,26 @@ class PulseIn:
|
|||
if DEBUG:
|
||||
print("Waiting for startup success message from subprocess")
|
||||
message = self._wait_receive_msg()
|
||||
if message[0] != b'!':
|
||||
if message[0] != b"!":
|
||||
raise RuntimeError("Could not establish message queue with subprocess")
|
||||
self._paused = False
|
||||
|
||||
# pylint: disable=redefined-builtin
|
||||
def _wait_receive_msg(self, timeout=0.25, type=2):
|
||||
"""Internal helper that will wait for new messages of a given type,
|
||||
and throw an exception on timeout"""
|
||||
stamp = time.monotonic()
|
||||
while (time.monotonic() - stamp) < timeout:
|
||||
try:
|
||||
message = self._mq.receive(block=False, type=2)
|
||||
message = self._mq.receive(block=False, type=type)
|
||||
return message
|
||||
except sysv_ipc.BusyError:
|
||||
time.sleep(0.001) # wait a bit then retry!
|
||||
# uh-oh timed out
|
||||
raise RuntimeError("Timed out waiting for PulseIn message")
|
||||
|
||||
# pylint: enable=redefined-builtin
|
||||
|
||||
def deinit(self):
|
||||
"""Deinitialises the PulseIn and releases any hardware and software
|
||||
resources for reuse."""
|
||||
|
|
@ -129,7 +139,7 @@ class PulseIn:
|
|||
"""Removes and returns the oldest read pulse."""
|
||||
self._mq.send("^", True, type=1)
|
||||
message = self._wait_receive_msg()
|
||||
reply = int(message[0].decode('utf-8'))
|
||||
reply = int(message[0].decode("utf-8"))
|
||||
# print(reply)
|
||||
if reply == -1:
|
||||
raise IndexError("pop from empty list")
|
||||
|
|
@ -139,13 +149,16 @@ class PulseIn:
|
|||
"""Returns the current pulse length"""
|
||||
self._mq.send("l", True, type=1)
|
||||
message = self._wait_receive_msg()
|
||||
return int(message[0].decode('utf-8'))
|
||||
return int(message[0].decode("utf-8"))
|
||||
|
||||
# pylint: disable=redefined-builtin
|
||||
def __getitem__(self, index, type=None):
|
||||
"""Returns the value at the given index or values in slice."""
|
||||
self._mq.send("i%d" % index, True, type=1)
|
||||
message = self._wait_receive_msg()
|
||||
ret = int(message[0].decode('utf-8'))
|
||||
ret = int(message[0].decode("utf-8"))
|
||||
if ret == -1:
|
||||
raise IndexError("list index out of range")
|
||||
return ret
|
||||
|
||||
# pylint: enable=redefined-builtin
|
||||
|
|
|
|||
|
|
@ -16,13 +16,14 @@ GPIO16 = Pin(16)
|
|||
TOUT = Pin("TOUT")
|
||||
|
||||
# ordered as spiId, sckId, mosiId, misoId
|
||||
SPI_PORTS = ((1, GPIO14, GPIO13, GPIO12))
|
||||
SPI_PORTS = (1, GPIO14, GPIO13, GPIO12)
|
||||
|
||||
# ordered as uartId, txId, rxId
|
||||
UART_PORTS = (
|
||||
(0, GPIO1, GPIO3),
|
||||
# TODO secondary pins for UART0 configurable from Micropython? How to flag?
|
||||
# (0, GPIO15, GPIO13)
|
||||
(1, GPIO2, None))
|
||||
(1, GPIO2, None),
|
||||
)
|
||||
|
||||
I2C_PORTS = ()
|
||||
|
|
|
|||
|
|
@ -1,37 +1,62 @@
|
|||
"""I2C Class for FT232H"""
|
||||
from adafruit_blinka.microcontroller.ft232h.pin import Pin
|
||||
|
||||
|
||||
class I2C:
|
||||
"""Custom I2C Class for FT232H"""
|
||||
|
||||
def __init__(self, *, frequency=400000):
|
||||
# change GPIO controller to I2C
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from pyftdi.i2c import I2cController
|
||||
|
||||
# pylint: enable=import-outside-toplevel
|
||||
|
||||
self._i2c = I2cController()
|
||||
self._i2c.configure('ftdi://ftdi:ft232h/1', frequency=frequency)
|
||||
self._i2c.configure("ftdi://ftdi:ft232h/1", frequency=frequency)
|
||||
Pin.ft232h_gpio = self._i2c.get_gpio()
|
||||
|
||||
def scan(self):
|
||||
"""Perform an I2C Device Scan"""
|
||||
return [addr for addr in range(0x79) if self._i2c.poll(addr)]
|
||||
|
||||
def writeto(self, address, buffer, *, start=0, end=None, stop=True):
|
||||
"""Write data from the buffer to an address"""
|
||||
end = end if end else len(buffer)
|
||||
port = self._i2c.get_port(address)
|
||||
port.write(buffer[start:end], relax=stop)
|
||||
|
||||
def readfrom_into(self, address, buffer, *, start=0, end=None, stop=True):
|
||||
"""Read data from an address and into the buffer"""
|
||||
end = end if end else len(buffer)
|
||||
port = self._i2c.get_port(address)
|
||||
result = port.read(len(buffer[start:end]), relax=stop)
|
||||
for i, b in enumerate(result):
|
||||
buffer[start + i] = b
|
||||
|
||||
def writeto_then_readfrom(self, address, buffer_out, buffer_in, *,
|
||||
out_start=0, out_end=None,
|
||||
in_start=0, in_end=None, stop=False):
|
||||
# pylint: disable=unused-argument
|
||||
def writeto_then_readfrom(
|
||||
self,
|
||||
address,
|
||||
buffer_out,
|
||||
buffer_in,
|
||||
*,
|
||||
out_start=0,
|
||||
out_end=None,
|
||||
in_start=0,
|
||||
in_end=None,
|
||||
stop=False
|
||||
):
|
||||
"""Write data from buffer_out to an address and then
|
||||
read data from an address and into buffer_in
|
||||
"""
|
||||
out_end = out_end if out_end else len(buffer_out)
|
||||
in_end = in_end if in_end else len(buffer_in)
|
||||
port = self._i2c.get_port(address)
|
||||
result = port.exchange(buffer_out[out_start:out_end],
|
||||
in_end-in_start,
|
||||
relax=True)
|
||||
result = port.exchange(
|
||||
buffer_out[out_start:out_end], in_end - in_start, relax=True
|
||||
)
|
||||
for i, b in enumerate(result):
|
||||
buffer_in[in_start + i] = b
|
||||
|
||||
# pylint: enable=unused-argument
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
"""FT232H pin names"""
|
||||
|
||||
|
||||
class Pin:
|
||||
"""A basic Pin class for use with FT232H."""
|
||||
|
||||
|
|
@ -12,7 +15,11 @@ class Pin:
|
|||
# setup GPIO controller if not done yet
|
||||
# use one provided by I2C as default
|
||||
if not Pin.ft232h_gpio:
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from pyftdi.i2c import I2cController
|
||||
|
||||
# pylint: enable=import-outside-toplevel
|
||||
|
||||
i2c = I2cController()
|
||||
i2c.configure("ftdi://ftdi:ft232h/1")
|
||||
Pin.ft232h_gpio = i2c.get_gpio()
|
||||
|
|
@ -24,6 +31,7 @@ class Pin:
|
|||
self.id = pin_id
|
||||
|
||||
def init(self, mode=IN, pull=None):
|
||||
"""Initialize the Pin"""
|
||||
if not self.id:
|
||||
raise RuntimeError("Can not init a None type pin.")
|
||||
# FT232H does't have configurable internal pulls?
|
||||
|
|
@ -38,6 +46,7 @@ class Pin:
|
|||
Pin.ft232h_gpio.set_direction(pin_mask, current)
|
||||
|
||||
def value(self, val=None):
|
||||
"""Set or return the Pin Value"""
|
||||
if not self.id:
|
||||
raise RuntimeError("Can not access a None type pin.")
|
||||
current = Pin.ft232h_gpio.read(with_output=True)
|
||||
|
|
@ -45,17 +54,18 @@ class Pin:
|
|||
if val is None:
|
||||
return 1 if current & 1 << self.id != 0 else 0
|
||||
# write
|
||||
elif val in (self.LOW, self.HIGH):
|
||||
if val in (self.LOW, self.HIGH):
|
||||
if val == self.HIGH:
|
||||
current |= 1 << self.id
|
||||
else:
|
||||
current &= ~(1 << self.id)
|
||||
# must mask out any input pins
|
||||
Pin.ft232h_gpio.write(current & Pin.ft232h_gpio.direction)
|
||||
return None
|
||||
# release the kraken
|
||||
else:
|
||||
raise RuntimeError("Invalid value for pin")
|
||||
|
||||
|
||||
# create pin instances for each pin
|
||||
# D0 to D3 are used by I2C/SPI
|
||||
D4 = Pin(4)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,20 @@
|
|||
"""SPI Class for FT232H"""
|
||||
from adafruit_blinka.microcontroller.ft232h.pin import Pin
|
||||
|
||||
# pylint: disable=protected-access
|
||||
class SPI:
|
||||
"""Custom SPI Class for FT232H"""
|
||||
|
||||
MSB = 0
|
||||
|
||||
def __init__(self):
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from pyftdi.spi import SpiController
|
||||
|
||||
# pylint: enable=import-outside-toplevel
|
||||
|
||||
self._spi = SpiController(cs_count=1)
|
||||
self._spi.configure('ftdi://ftdi:ft232h/1')
|
||||
self._spi.configure("ftdi://ftdi:ft232h/1")
|
||||
self._port = self._spi.get_port(0)
|
||||
self._port.set_frequency(100000)
|
||||
self._port._cpol = 0
|
||||
|
|
@ -14,8 +22,19 @@ class SPI:
|
|||
# Change GPIO controller to SPI
|
||||
Pin.ft232h_gpio = self._spi.get_gpio()
|
||||
|
||||
def init(self, baudrate=100000, polarity=0, phase=0, bits=8,
|
||||
firstbit=MSB, sck=None, mosi=None, miso=None):
|
||||
# pylint: disable=too-many-arguments
|
||||
def init(
|
||||
self,
|
||||
baudrate=100000,
|
||||
polarity=0,
|
||||
phase=0,
|
||||
bits=8,
|
||||
firstbit=MSB,
|
||||
sck=None,
|
||||
mosi=None,
|
||||
miso=None,
|
||||
):
|
||||
"""Initialize the Port"""
|
||||
self._port.set_frequency(baudrate)
|
||||
# FTDI device can only support mode 0 and mode 2
|
||||
# due to the limitation of MPSSE engine.
|
||||
|
|
@ -25,11 +44,15 @@ class SPI:
|
|||
raise ValueError("Only SPI phase 0 is supported by FT232H.")
|
||||
self._port._cpha = phase
|
||||
|
||||
# pylint: enable=too-many-arguments
|
||||
|
||||
@property
|
||||
def frequency(self):
|
||||
"""Return the current frequency"""
|
||||
return self._port.frequency
|
||||
|
||||
def write(self, buf, start=0, end=None):
|
||||
"""Write data from the buffer to SPI"""
|
||||
end = end if end else len(buf)
|
||||
chunks, rest = divmod(end - start, self._spi.PAYLOAD_MAX_LENGTH)
|
||||
for i in range(chunks):
|
||||
|
|
@ -39,16 +62,29 @@ class SPI:
|
|||
if rest:
|
||||
self._port.write(buf[-1 * rest :])
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def readinto(self, buf, start=0, end=None, write_value=0):
|
||||
"""Read data from SPI and into the buffer"""
|
||||
end = end if end else len(buf)
|
||||
result = self._port.read(end - start)
|
||||
for i, b in enumerate(result):
|
||||
buf[start + i] = b
|
||||
|
||||
def write_readinto(self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None):
|
||||
# pylint: enable=unused-argument
|
||||
|
||||
# pylint: disable=too-many-arguments
|
||||
def write_readinto(
|
||||
self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
|
||||
):
|
||||
"""Perform a half-duplex write from buffer_out and then
|
||||
read data into buffer_in
|
||||
"""
|
||||
out_end = out_end if out_end else len(buffer_out)
|
||||
in_end = in_end if in_end else len(buffer_in)
|
||||
result = self._port.exchange(buffer_out[out_start:out_end],
|
||||
in_end-in_start, duplex=True)
|
||||
result = self._port.exchange(
|
||||
buffer_out[out_start:out_end], in_end - in_start, duplex=True
|
||||
)
|
||||
for i, b in enumerate(result):
|
||||
buffer_in[in_start + i] = b
|
||||
|
||||
# pylint: enable=too-many-arguments
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
"""Generic Linux I2C class using PureIO's smbus class"""
|
||||
import Adafruit_PureIO.smbus as smbus
|
||||
import time
|
||||
|
||||
|
||||
class I2C:
|
||||
"""I2C class"""
|
||||
|
||||
MASTER = 0
|
||||
SLAVE = 1
|
||||
_baudrate = None
|
||||
|
|
@ -19,10 +22,13 @@ class I2C:
|
|||
try:
|
||||
self._i2c_bus = smbus.SMBus(bus_num)
|
||||
except FileNotFoundError:
|
||||
raise RuntimeError("I2C Bus #%d not found, check if enabled in config!" % bus_num)
|
||||
raise RuntimeError(
|
||||
"I2C Bus #%d not found, check if enabled in config!" % bus_num
|
||||
)
|
||||
|
||||
def scan(self):
|
||||
"""Try to read a byte from each address, if you get an OSError it means the device isnt there"""
|
||||
"""Try to read a byte from each address, if you get an OSError
|
||||
it means the device isnt there"""
|
||||
found = []
|
||||
for addr in range(0, 0x80):
|
||||
try:
|
||||
|
|
@ -32,12 +38,15 @@ class I2C:
|
|||
found.append(addr)
|
||||
return found
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def writeto(self, address, buffer, *, start=0, end=None, stop=True):
|
||||
"""Write data from the buffer to an address"""
|
||||
if end is None:
|
||||
end = len(buffer)
|
||||
self._i2c_bus.write_bytes(address, buffer[start:end])
|
||||
|
||||
def readfrom_into(self, address, buffer, *, start=0, end=None, stop=True):
|
||||
"""Read data from an address and into the buffer"""
|
||||
if end is None:
|
||||
end = len(buffer)
|
||||
|
||||
|
|
@ -45,9 +54,23 @@ class I2C:
|
|||
for i in range(end - start):
|
||||
buffer[i + start] = readin[i]
|
||||
|
||||
def writeto_then_readfrom(self, address, buffer_out, buffer_in, *,
|
||||
out_start=0, out_end=None,
|
||||
in_start=0, in_end=None, stop=False):
|
||||
# pylint: enable=unused-argument
|
||||
|
||||
def writeto_then_readfrom(
|
||||
self,
|
||||
address,
|
||||
buffer_out,
|
||||
buffer_in,
|
||||
*,
|
||||
out_start=0,
|
||||
out_end=None,
|
||||
in_start=0,
|
||||
in_end=None,
|
||||
stop=False
|
||||
):
|
||||
"""Write data from buffer_out to an address and then
|
||||
read data from an address and into buffer_in
|
||||
"""
|
||||
if out_end is None:
|
||||
out_end = len(buffer_out)
|
||||
if in_end is None:
|
||||
|
|
@ -58,7 +81,8 @@ class I2C:
|
|||
self.readfrom_into(address, buffer_in, start=in_start, end=in_end)
|
||||
else:
|
||||
# To generate without a stop, do in one block transaction
|
||||
readin = self._i2c_bus.read_i2c_block_data(address, buffer_out[out_start:out_end], in_end-in_start)
|
||||
readin = self._i2c_bus.read_i2c_block_data(
|
||||
address, buffer_out[out_start:out_end], in_end - in_start
|
||||
)
|
||||
for i in range(in_end - in_start):
|
||||
buffer_in[i + in_start] = readin[i]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,16 @@
|
|||
"""A Pin class for use with libgpiod."""
|
||||
try:
|
||||
import gpiod
|
||||
except ImportError:
|
||||
raise ImportError("libgpiod Python bindings not found, please install and try again! See https://github.com/adafruit/Raspberry-Pi-Installer-Scripts/blob/master/libgpiod.sh")
|
||||
raise ImportError(
|
||||
"libgpiod Python bindings not found, please install and try again! See "
|
||||
"https://github.com/adafruit/Raspberry-Pi-Installer-Scripts/blob/master/libgpiod.sh"
|
||||
)
|
||||
|
||||
|
||||
# Pins dont exist in CPython so...lets make our own!
|
||||
class Pin:
|
||||
"""Pins dont exist in CPython so...lets make our own!"""
|
||||
|
||||
IN = 0
|
||||
OUT = 1
|
||||
LOW = 0
|
||||
|
|
@ -12,7 +18,7 @@ class Pin:
|
|||
PULL_NONE = 0
|
||||
PULL_UP = 1
|
||||
PULL_DOWN = 2
|
||||
_CONSUMER = 'adafruit_blinka'
|
||||
_CONSUMER = "adafruit_blinka"
|
||||
|
||||
id = None
|
||||
_value = LOW
|
||||
|
|
@ -20,7 +26,7 @@ class Pin:
|
|||
|
||||
def __init__(self, pin_id):
|
||||
self.id = pin_id
|
||||
if type(pin_id) is tuple:
|
||||
if isinstance(pin_id, tuple):
|
||||
self._num = int(pin_id[1])
|
||||
self._chip = gpiod.Chip(str(pin_id[0]), gpiod.Chip.OPEN_BY_NUMBER)
|
||||
else:
|
||||
|
|
@ -35,44 +41,50 @@ class Pin:
|
|||
return self.id == other
|
||||
|
||||
def init(self, mode=IN, pull=None):
|
||||
"""Initialize the Pin"""
|
||||
if not self._line:
|
||||
self._line = self._chip.get_line(int(self._num))
|
||||
# print("init line: ", self.id, self._line)
|
||||
|
||||
if mode != None:
|
||||
if mode is not None:
|
||||
if mode == self.IN:
|
||||
flags = 0
|
||||
if pull != None:
|
||||
if pull is not None:
|
||||
if pull == self.PULL_UP:
|
||||
raise NotImplementedError("Internal pullups not supported in libgpiod, use physical resistor instead!")
|
||||
elif pull == self.PULL_DOWN:
|
||||
raise NotImplementedError("Internal pulldowns not supported in libgpiod, use physical resistor instead!")
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
"Internal pullups not supported in libgpiod, "
|
||||
"use physical resistor instead!"
|
||||
)
|
||||
if pull == self.PULL_DOWN:
|
||||
raise NotImplementedError(
|
||||
"Internal pulldowns not supported in libgpiod, "
|
||||
"use physical resistor instead!"
|
||||
)
|
||||
raise RuntimeError("Invalid pull for pin: %s" % self.id)
|
||||
|
||||
self._mode = self.IN
|
||||
self._line.release()
|
||||
self._line.request(consumer=self._CONSUMER,
|
||||
type=gpiod.LINE_REQ_DIR_IN,
|
||||
flags=flags)
|
||||
self._line.request(
|
||||
consumer=self._CONSUMER, type=gpiod.LINE_REQ_DIR_IN, flags=flags
|
||||
)
|
||||
|
||||
elif mode == self.OUT:
|
||||
if pull != None:
|
||||
if pull is not None:
|
||||
raise RuntimeError("Cannot set pull resistor on output")
|
||||
self._mode = self.OUT
|
||||
self._line.release()
|
||||
self._line.request(consumer=self._CONSUMER,
|
||||
type=gpiod.LINE_REQ_DIR_OUT)
|
||||
self._line.request(consumer=self._CONSUMER, type=gpiod.LINE_REQ_DIR_OUT)
|
||||
|
||||
else:
|
||||
raise RuntimeError("Invalid mode for pin: %s" % self.id)
|
||||
|
||||
def value(self, val=None):
|
||||
if val != None:
|
||||
"""Set or return the Pin Value"""
|
||||
if val is None:
|
||||
return self._line.get_value()
|
||||
|
||||
if val in (self.LOW, self.HIGH):
|
||||
self._value = val
|
||||
self._line.set_value(val)
|
||||
else:
|
||||
return None
|
||||
raise RuntimeError("Invalid value for pin")
|
||||
else:
|
||||
return self._line.get_value()
|
||||
|
|
|
|||
|
|
@ -1,10 +1,16 @@
|
|||
"""A Pin class for use with periphery."""
|
||||
try:
|
||||
from periphery import GPIO
|
||||
except ImportError:
|
||||
raise ImportError("Periphery Python bindings not found, please install and try again! Try running 'pip3 install python-periphery'")
|
||||
raise ImportError(
|
||||
"Periphery Python bindings not found, please install and try again! "
|
||||
"Try running 'pip3 install python-periphery'"
|
||||
)
|
||||
|
||||
|
||||
# Pins dont exist in CPython so...lets make our own!
|
||||
class Pin:
|
||||
"""Pins dont exist in CPython so...lets make our own!"""
|
||||
|
||||
IN = "in"
|
||||
OUT = "out"
|
||||
LOW = 0
|
||||
|
|
@ -12,7 +18,6 @@ class Pin:
|
|||
PULL_NONE = 0
|
||||
PULL_UP = 1
|
||||
PULL_DOWN = 2
|
||||
_CONSUMER = 'adafruit_blinka'
|
||||
|
||||
id = None
|
||||
_value = LOW
|
||||
|
|
@ -20,7 +25,7 @@ class Pin:
|
|||
|
||||
def __init__(self, pin_id):
|
||||
self.id = pin_id
|
||||
if type(pin_id) is tuple:
|
||||
if isinstance(pin_id, tuple):
|
||||
self._num = int(pin_id[1])
|
||||
self._chippath = "/dev/gpiochip{}".format(pin_id[0])
|
||||
else:
|
||||
|
|
@ -35,7 +40,8 @@ class Pin:
|
|||
return self.id == other
|
||||
|
||||
def init(self, mode=IN, pull=None):
|
||||
if mode != None:
|
||||
"""Initialize the Pin"""
|
||||
if mode is not None:
|
||||
if mode == self.IN:
|
||||
self._mode = self.IN
|
||||
if self._line is not None:
|
||||
|
|
@ -49,24 +55,29 @@ class Pin:
|
|||
else:
|
||||
raise RuntimeError("Invalid mode for pin: %s" % self.id)
|
||||
|
||||
if pull != None:
|
||||
if pull is not None:
|
||||
if pull == self.PULL_UP:
|
||||
raise NotImplementedError("Internal pullups not supported in periphery, use physical resistor instead!")
|
||||
elif pull == self.PULL_DOWN:
|
||||
raise NotImplementedError("Internal pulldowns not supported in periphery, use physical resistor instead!")
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
"Internal pullups not supported in periphery, "
|
||||
"use physical resistor instead!"
|
||||
)
|
||||
if pull == self.PULL_DOWN:
|
||||
raise NotImplementedError(
|
||||
"Internal pulldowns not supported in periphery, "
|
||||
"use physical resistor instead!"
|
||||
)
|
||||
raise RuntimeError("Invalid pull for pin: %s" % self.id)
|
||||
|
||||
def value(self, val=None):
|
||||
if val != None:
|
||||
"""Set or return the Pin Value"""
|
||||
if val is not None:
|
||||
if val == self.LOW:
|
||||
self._value = val
|
||||
self._line.write(False)
|
||||
elif val == self.HIGH:
|
||||
return None
|
||||
if val == self.HIGH:
|
||||
self._value = val
|
||||
self._line.write(True)
|
||||
else:
|
||||
return None
|
||||
raise RuntimeError("Invalid value for pin")
|
||||
else:
|
||||
return self.HIGH if self._line.read() else self.LOW
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
"""Generic Linux SPI class using PureIO's SPI class"""
|
||||
import Adafruit_PureIO.spi as spi
|
||||
import time
|
||||
from adafruit_blinka.agnostic import detector
|
||||
|
||||
|
||||
class SPI:
|
||||
"""SPI Class"""
|
||||
|
||||
MSB = 0
|
||||
LSB = 1
|
||||
CPHA = 1
|
||||
|
|
@ -17,9 +20,24 @@ class SPI:
|
|||
self._spi = spi.SPI(device=portid)
|
||||
else:
|
||||
self._spi = spi.SPI(device=(portid, 0))
|
||||
self.clock_pin = None
|
||||
self.mosi_pin = None
|
||||
self.miso_pin = None
|
||||
self.chip = None
|
||||
|
||||
def init(self, baudrate=100000, polarity=0, phase=0, bits=8,
|
||||
firstbit=MSB, sck=None, mosi=None, miso=None):
|
||||
# pylint: disable=too-many-arguments,unused-argument
|
||||
def init(
|
||||
self,
|
||||
baudrate=100000,
|
||||
polarity=0,
|
||||
phase=0,
|
||||
bits=8,
|
||||
firstbit=MSB,
|
||||
sck=None,
|
||||
mosi=None,
|
||||
miso=None,
|
||||
):
|
||||
"""Initialize SPI"""
|
||||
mode = 0
|
||||
if polarity:
|
||||
mode |= self.CPOL
|
||||
|
|
@ -35,15 +53,23 @@ class SPI:
|
|||
self.mosi_pin = mosi
|
||||
self.miso_pin = miso
|
||||
|
||||
# pylint: enable=too-many-arguments,unused-argument
|
||||
|
||||
# pylint: disable=unnecessary-pass
|
||||
def set_no_cs(self):
|
||||
"""Setting so that SPI doesn't automatically set the CS pin"""
|
||||
# No kernel seems to support this, so we're just going to pass
|
||||
pass
|
||||
|
||||
# pylint: enable=unnecessary-pass
|
||||
|
||||
@property
|
||||
def frequency(self):
|
||||
"""Return the current baudrate"""
|
||||
return self.baudrate
|
||||
|
||||
def write(self, buf, start=0, end=None):
|
||||
"""Write data from the buffer to SPI"""
|
||||
if not buf:
|
||||
return
|
||||
if end is None:
|
||||
|
|
@ -56,11 +82,12 @@ class SPI:
|
|||
self._spi.bits_per_word = self.bits
|
||||
self._spi.writebytes(buf[start:end])
|
||||
# self._spi.close()
|
||||
except FileNotFoundError as not_found:
|
||||
except FileNotFoundError:
|
||||
print("Could not open SPI device - check if SPI is enabled in kernel!")
|
||||
raise
|
||||
|
||||
def readinto(self, buf, start=0, end=None, write_value=0):
|
||||
"""Read data from SPI and into the buffer"""
|
||||
if not buf:
|
||||
return
|
||||
if end is None:
|
||||
|
|
@ -75,12 +102,17 @@ class SPI:
|
|||
for i in range(end - start): # 'readinto' the given buffer
|
||||
buf[start + i] = data[i]
|
||||
# self._spi.close()
|
||||
except FileNotFoundError as not_found:
|
||||
except FileNotFoundError:
|
||||
print("Could not open SPI device - check if SPI is enabled in kernel!")
|
||||
raise
|
||||
|
||||
def write_readinto(self, buffer_out, buffer_in, out_start=0,
|
||||
out_end=None, in_start=0, in_end=None):
|
||||
# pylint: disable=too-many-arguments
|
||||
def write_readinto(
|
||||
self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
|
||||
):
|
||||
"""Perform a half-duplex write from buffer_out and then
|
||||
read data into buffer_in
|
||||
"""
|
||||
if not buffer_out or not buffer_in:
|
||||
return
|
||||
if out_end is None:
|
||||
|
|
@ -88,7 +120,7 @@ class SPI:
|
|||
if in_end is None:
|
||||
in_end = len(buffer_in)
|
||||
if out_end - out_start != in_end - in_start:
|
||||
raise RuntimeError('Buffer slices must be of equal length.')
|
||||
raise RuntimeError("Buffer slices must be of equal length.")
|
||||
try:
|
||||
# self._spi.open(self._port, 0)
|
||||
# self.set_no_cs()
|
||||
|
|
@ -99,6 +131,8 @@ class SPI:
|
|||
for i in range((in_end - in_start)):
|
||||
buffer_in[i + in_start] = data[i]
|
||||
# self._spi.close()
|
||||
except FileNotFoundError as not_found:
|
||||
except FileNotFoundError:
|
||||
print("Could not open SPI device - check if SPI is enabled in kernel!")
|
||||
raise
|
||||
|
||||
# pylint: enable=too-many-arguments
|
||||
|
|
|
|||
|
|
@ -1,21 +1,30 @@
|
|||
# Much code from https://github.com/vsergeev/python-periphery/blob/master/periphery/pwm.py
|
||||
# Copyright (c) 2015-2016 vsergeev / Ivan (Vanya) A. Sergeev
|
||||
# License: MIT
|
||||
"""
|
||||
Much code from https://github.com/vsergeev/python-periphery/blob/master/periphery/pwm.py
|
||||
Copyright (c) 2015-2016 vsergeev / Ivan (Vanya) A. Sergeev
|
||||
License: MIT
|
||||
"""
|
||||
|
||||
import os
|
||||
import digitalio
|
||||
|
||||
try:
|
||||
from microcontroller.pin import pwmOuts
|
||||
except ImportError:
|
||||
raise RuntimeError("No PWM outputs defined for this board")
|
||||
|
||||
|
||||
# pylint: disable=unnecessary-pass
|
||||
class PWMError(IOError):
|
||||
"""Base class for PWM errors."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class PWMOut(object):
|
||||
# pylint: enable=unnecessary-pass
|
||||
|
||||
|
||||
class PWMOut:
|
||||
"""Pulse Width Modulation Output Class"""
|
||||
|
||||
# Sysfs paths
|
||||
_sysfs_path = "/sys/class/pwm/"
|
||||
_channel_path = "pwmchip{}"
|
||||
|
|
@ -52,6 +61,8 @@ class PWMOut(object):
|
|||
"""
|
||||
|
||||
self._pwmpin = None
|
||||
self._channel = None
|
||||
self._period = 0
|
||||
self._open(pin, duty_cycle, frequency, variable_frequency)
|
||||
|
||||
def __del__(self):
|
||||
|
|
@ -74,13 +85,19 @@ class PWMOut(object):
|
|||
if self._channel is None:
|
||||
raise RuntimeError("No PWM channel found for this Pin")
|
||||
|
||||
channel_path = os.path.join(self._sysfs_path, self._channel_path.format(self._channel))
|
||||
channel_path = os.path.join(
|
||||
self._sysfs_path, self._channel_path.format(self._channel)
|
||||
)
|
||||
if not os.path.isdir(channel_path):
|
||||
raise ValueError("PWM channel does not exist, check that the required modules are loaded.")
|
||||
raise ValueError(
|
||||
"PWM channel does not exist, check that the required modules are loaded."
|
||||
)
|
||||
|
||||
pin_path = os.path.join(channel_path, self._pin_path.format(self._pwmpin))
|
||||
try:
|
||||
with open(os.path.join(channel_path, self._unexport_path), "w") as f_unexport:
|
||||
with open(
|
||||
os.path.join(channel_path, self._unexport_path), "w"
|
||||
) as f_unexport:
|
||||
f_unexport.write("%d\n" % self._pwmpin)
|
||||
except IOError as e:
|
||||
pass # not unusual, it doesnt already exist
|
||||
|
|
@ -109,8 +126,12 @@ class PWMOut(object):
|
|||
if self._channel is not None:
|
||||
self.duty_cycle = 0
|
||||
try:
|
||||
channel_path = os.path.join(self._sysfs_path, self._channel_path.format(self._channel))
|
||||
with open(os.path.join(channel_path, self._unexport_path), "w") as f_unexport:
|
||||
channel_path = os.path.join(
|
||||
self._sysfs_path, self._channel_path.format(self._channel)
|
||||
)
|
||||
with open(
|
||||
os.path.join(channel_path, self._unexport_path), "w"
|
||||
) as f_unexport:
|
||||
f_unexport.write("%d\n" % self._pwmpin)
|
||||
except IOError as e:
|
||||
raise PWMError(e.errno, "Unexporting PWM pin: " + e.strerror)
|
||||
|
|
@ -120,8 +141,10 @@ class PWMOut(object):
|
|||
|
||||
def _is_deinited(self):
|
||||
if self._pwmpin is None:
|
||||
raise ValueError("Object has been deinitialize and can no longer "
|
||||
"be used. Create a new object.")
|
||||
raise ValueError(
|
||||
"Object has been deinitialize and can no longer "
|
||||
"be used. Create a new object."
|
||||
)
|
||||
|
||||
def _write_pin_attr(self, attr, value):
|
||||
# Make sure the pin is active
|
||||
|
|
@ -131,9 +154,10 @@ class PWMOut(object):
|
|||
self._sysfs_path,
|
||||
self._channel_path.format(self._channel),
|
||||
self._pin_path.format(self._pwmpin),
|
||||
attr)
|
||||
attr,
|
||||
)
|
||||
|
||||
with open(path, 'w') as f_attr:
|
||||
with open(path, "w") as f_attr:
|
||||
# print(value, path)
|
||||
f_attr.write(value + "\n")
|
||||
|
||||
|
|
@ -145,9 +169,10 @@ class PWMOut(object):
|
|||
self._sysfs_path,
|
||||
self._channel_path.format(self._channel),
|
||||
self._pin_path.format(self._pwmpin),
|
||||
attr)
|
||||
attr,
|
||||
)
|
||||
|
||||
with open(path, 'r') as f_attr:
|
||||
with open(path, "r") as f_attr:
|
||||
return f_attr.read().strip()
|
||||
|
||||
# Mutable properties
|
||||
|
|
@ -157,7 +182,7 @@ class PWMOut(object):
|
|||
try:
|
||||
period_ns = int(period_ns)
|
||||
except ValueError:
|
||||
raise PWMError(None, "Unknown period value: \"%s\"" % period_ns)
|
||||
raise PWMError(None, 'Unknown period value: "%s"' % period_ns)
|
||||
|
||||
# Convert period from nanoseconds to seconds
|
||||
period = period_ns / 1e9
|
||||
|
|
@ -195,7 +220,7 @@ class PWMOut(object):
|
|||
try:
|
||||
duty_cycle_ns = int(duty_cycle_ns)
|
||||
except ValueError:
|
||||
raise PWMError(None, "Unknown duty cycle value: \"%s\"" % duty_cycle_ns)
|
||||
raise PWMError(None, 'Unknown duty cycle value: "%s"' % duty_cycle_ns)
|
||||
|
||||
# Convert duty cycle from nanoseconds to seconds
|
||||
duty_cycle = duty_cycle_ns / 1e9
|
||||
|
|
@ -259,17 +284,12 @@ class PWMOut(object):
|
|||
|
||||
if enabled == "1":
|
||||
return True
|
||||
elif enabled == "0":
|
||||
if enabled == "0":
|
||||
return False
|
||||
|
||||
raise PWMError(None, "Unknown enabled value: \"%s\"" % enabled)
|
||||
raise PWMError(None, 'Unknown enabled value: "%s"' % enabled)
|
||||
|
||||
def _set_enabled(self, value):
|
||||
if not isinstance(value, bool):
|
||||
raise TypeError("Invalid enabled type, should be string.")
|
||||
|
||||
self._write_pin_attr(self._pin_enable_path, "1" if value else "0")
|
||||
|
||||
"""Get or set the PWM's output enabled state.
|
||||
|
||||
Raises:
|
||||
|
|
@ -278,9 +298,17 @@ class PWMOut(object):
|
|||
|
||||
:type: bool
|
||||
"""
|
||||
if not isinstance(value, bool):
|
||||
raise TypeError("Invalid enabled type, should be string.")
|
||||
|
||||
self._write_pin_attr(self._pin_enable_path, "1" if value else "0")
|
||||
|
||||
# String representation
|
||||
|
||||
def __str__(self):
|
||||
return "PWM%d, pin %s (freq=%f Hz, duty_cycle=%f%%)" % \
|
||||
(self._channel, self._pin, self.frequency, self.duty_cycle * 100,)
|
||||
return "PWM%d, pin %s (freq=%f Hz, duty_cycle=%f%%)" % (
|
||||
self._channel,
|
||||
self._pin,
|
||||
self.frequency,
|
||||
self.duty_cycle * 100,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ SPI0_DIN = Pin(10)
|
|||
UART1_TXD = Pin(11)
|
||||
SPI0_CS = Pin(12)
|
||||
UART1_RXD = Pin(13)
|
||||
SPIO0_DOUT = Pin(14)
|
||||
SPI0_DOUT = Pin(14)
|
||||
I2C0_SCL = Pin(15)
|
||||
I2C0_SDA = Pin(17)
|
||||
GPIO0 = Pin(23)
|
||||
|
|
@ -25,14 +25,14 @@ GPIO9 = Pin(32)
|
|||
GPIO15 = Pin(33)
|
||||
|
||||
# ordered as spiId, sckId, mosiId, misoId
|
||||
SPI_PORTS = ((1, SPI0_SCLK, SPI0_DOUT, SPI0_DIN))
|
||||
SPI_PORTS = (1, SPI0_SCLK, SPI0_DOUT, SPI0_DIN)
|
||||
|
||||
# ordered as uartId, txId, rxId
|
||||
UART_PORTS = (
|
||||
(0, UART0_TXD, UART0_RXD),
|
||||
# (0, GPIO15, GPIO13)
|
||||
(1, UART1_TXD, UART1_RXD))
|
||||
(1, UART1_TXD, UART1_RXD),
|
||||
)
|
||||
|
||||
# ordered as spiId, spiSCA, spiSCL
|
||||
I2C_PORTS = (
|
||||
(0, I2C0_SCA, I2C0_SCL))
|
||||
# ordered as i2cId, sclId, sdaId
|
||||
I2C_PORTS = (0, I2C0_SDA, I2C0_SCL)
|
||||
|
|
|
|||
|
|
@ -1,23 +1,50 @@
|
|||
"""I2C Class for MCP2221"""
|
||||
from .mcp2221 import mcp2221
|
||||
|
||||
|
||||
class I2C:
|
||||
"""Custom I2C Class for MCP2221"""
|
||||
|
||||
def __init__(self, *, frequency=100000):
|
||||
self._mcp2221 = mcp2221
|
||||
self._mcp2221.i2c_configure(frequency)
|
||||
|
||||
def scan(self):
|
||||
"""Perform an I2C Device Scan"""
|
||||
return self._mcp2221.i2c_scan()
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def writeto(self, address, buffer, *, start=0, end=None, stop=True):
|
||||
"""Write data from the buffer to an address"""
|
||||
self._mcp2221.i2c_writeto(address, buffer, start=start, end=end)
|
||||
|
||||
def readfrom_into(self, address, buffer, *, start=0, end=None, stop=True):
|
||||
"""Read data from an address and into the buffer"""
|
||||
self._mcp2221.i2c_readfrom_into(address, buffer, start=start, end=end)
|
||||
|
||||
def writeto_then_readfrom(self, address, buffer_out, buffer_in, *,
|
||||
out_start=0, out_end=None,
|
||||
in_start=0, in_end=None, stop=False):
|
||||
self._mcp2221.i2c_writeto_then_readfrom(address, buffer_out, buffer_in,
|
||||
out_start=out_start, out_end=out_end,
|
||||
in_start=in_start, in_end=in_end)
|
||||
def writeto_then_readfrom(
|
||||
self,
|
||||
address,
|
||||
buffer_out,
|
||||
buffer_in,
|
||||
*,
|
||||
out_start=0,
|
||||
out_end=None,
|
||||
in_start=0,
|
||||
in_end=None,
|
||||
stop=False
|
||||
):
|
||||
"""Write data from buffer_out to an address and then
|
||||
read data from an address and into buffer_in
|
||||
"""
|
||||
self._mcp2221.i2c_writeto_then_readfrom(
|
||||
address,
|
||||
buffer_out,
|
||||
buffer_in,
|
||||
out_start=out_start,
|
||||
out_end=out_end,
|
||||
in_start=in_start,
|
||||
in_end=in_end,
|
||||
)
|
||||
|
||||
# pylint: enable=unused-argument
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
"""Chip Definition for MCP2221"""
|
||||
|
||||
import os
|
||||
import time
|
||||
import hid
|
||||
|
||||
# Here if you need it
|
||||
MCP2221_HID_DELAY = float(os.environ.get('BLINKA_MCP2221_HID_DELAY', 0))
|
||||
MCP2221_HID_DELAY = float(os.environ.get("BLINKA_MCP2221_HID_DELAY", 0))
|
||||
# Use to set delay between reset and device reopen
|
||||
MCP2221_RESET_DELAY = float(os.environ.get('BLINKA_MCP2221_RESET_DELAY', 0.5))
|
||||
MCP2221_RESET_DELAY = float(os.environ.get("BLINKA_MCP2221_RESET_DELAY", 0.5))
|
||||
|
||||
# from the C driver
|
||||
# http://ww1.microchip.com/downloads/en/DeviceDoc/mcp2221_0_1.tar.gz
|
||||
|
|
@ -35,7 +37,9 @@ MCP2221_MAX_I2C_DATA_LEN = 60
|
|||
MASK_ADDR_NACK = 0x40
|
||||
# pylint: enable=bad-whitespace
|
||||
|
||||
|
||||
class MCP2221:
|
||||
"""MCP2221 Device Class Definition"""
|
||||
|
||||
VID = 0x04D8
|
||||
PID = 0x00DD
|
||||
|
|
@ -52,26 +56,30 @@ class MCP2221:
|
|||
self._reset()
|
||||
|
||||
def _hid_xfer(self, report, response=True):
|
||||
"""Perform HID Transfer"""
|
||||
# first byte is report ID, which =0 for MCP2221
|
||||
# remaing bytes = 64 byte report data
|
||||
# https://github.com/libusb/hidapi/blob/083223e77952e1ef57e6b77796536a3359c1b2a3/hidapi/hidapi.h#L185
|
||||
self._hid.write(b'\0' + report + b'\0'*(64-len(report)))
|
||||
self._hid.write(b"\0" + report + b"\0" * (64 - len(report)))
|
||||
time.sleep(MCP2221_HID_DELAY)
|
||||
if response:
|
||||
# return is 64 byte response report
|
||||
return self._hid.read(64)
|
||||
return None
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# MISC
|
||||
# ----------------------------------------------------------------
|
||||
def gp_get_mode(self, pin):
|
||||
return self._hid_xfer(b'\x61')[22+pin] & 0x07
|
||||
"""Get Current Pin Mode"""
|
||||
return self._hid_xfer(b"\x61")[22 + pin] & 0x07
|
||||
|
||||
def gp_set_mode(self, pin, mode):
|
||||
"""Set Current Pin Mode"""
|
||||
# get current settings
|
||||
current = self._hid_xfer(b'\x61')
|
||||
current = self._hid_xfer(b"\x61")
|
||||
# empty report, this is safe since 0's = no change
|
||||
report = bytearray(b'\x60'+b'\x00'*63)
|
||||
report = bytearray(b"\x60" + b"\x00" * 63)
|
||||
# set the alter GP flag byte
|
||||
report[7] = 0xFF
|
||||
# each pin can be set individually
|
||||
|
|
@ -86,26 +94,27 @@ class MCP2221:
|
|||
# and make it so
|
||||
self._hid_xfer(report)
|
||||
|
||||
def _pretty_report(self, report):
|
||||
def _pretty_report(self, register):
|
||||
report = self._hid_xfer(register)
|
||||
print(" 0 1 2 3 4 5 6 7 8 9")
|
||||
index = 0
|
||||
for row in range(7):
|
||||
print("{} : ".format(row), end='')
|
||||
print("{} : ".format(row), end="")
|
||||
for _ in range(10):
|
||||
print("{:02x} ".format(report[index]), end='')
|
||||
print("{:02x} ".format(report[index]), end="")
|
||||
index += 1
|
||||
if index > 63:
|
||||
break
|
||||
print()
|
||||
|
||||
def _status_dump(self):
|
||||
self._pretty_report(self._hid_xfer(b'\x10'))
|
||||
self._pretty_report(b"\x10")
|
||||
|
||||
def _sram_dump(self):
|
||||
self._pretty_report(self._hid_xfer(b'\x61'))
|
||||
self._pretty_report(b"\x61")
|
||||
|
||||
def _reset(self):
|
||||
self._hid_xfer(b'\x70\xAB\xCD\xEF', response=False)
|
||||
self._hid_xfer(b"\x70\xAB\xCD\xEF", response=False)
|
||||
time.sleep(MCP2221_RESET_DELAY)
|
||||
start = time.monotonic()
|
||||
while time.monotonic() - start < 5:
|
||||
|
|
@ -122,32 +131,34 @@ class MCP2221:
|
|||
# GPIO
|
||||
# ----------------------------------------------------------------
|
||||
def gpio_set_direction(self, pin, mode):
|
||||
report = bytearray(b'\x50'+b'\x00'*63) # empty set GPIO report
|
||||
"""Set Current GPIO Pin Direction"""
|
||||
report = bytearray(b"\x50" + b"\x00" * 63) # empty set GPIO report
|
||||
offset = 4 * (pin + 1)
|
||||
report[offset] = 0x01 # set pin direction
|
||||
report[offset + 1] = mode # to this
|
||||
self._hid_xfer(report)
|
||||
|
||||
def gpio_set_pin(self, pin, value):
|
||||
report = bytearray(b'\x50'+b'\x00'*63) # empty set GPIO report
|
||||
"""Set Current GPIO Pin Value"""
|
||||
report = bytearray(b"\x50" + b"\x00" * 63) # empty set GPIO report
|
||||
offset = 2 + 4 * pin
|
||||
report[offset] = 0x01 # set pin value
|
||||
report[offset + 1] = value # to this
|
||||
self._hid_xfer(report)
|
||||
|
||||
def gpio_get_pin(self, pin):
|
||||
resp = self._hid_xfer(b'\x51')
|
||||
"""Get Current GPIO Pin Value"""
|
||||
resp = self._hid_xfer(b"\x51")
|
||||
offset = 2 + 2 * pin
|
||||
if resp[offset] == 0xEE:
|
||||
raise RuntimeError("Pin is not set for GPIO operation.")
|
||||
else:
|
||||
return resp[offset]
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# I2C
|
||||
# ----------------------------------------------------------------
|
||||
def _i2c_status(self):
|
||||
resp = self._hid_xfer(b'\x10')
|
||||
resp = self._hid_xfer(b"\x10")
|
||||
if resp[1] != 0:
|
||||
raise RuntimeError("Couldn't get I2C status")
|
||||
return resp
|
||||
|
|
@ -156,13 +167,14 @@ class MCP2221:
|
|||
return self._i2c_status()[8]
|
||||
|
||||
def _i2c_cancel(self):
|
||||
resp = self._hid_xfer(b'\x10\x00\x10')
|
||||
resp = self._hid_xfer(b"\x10\x00\x10")
|
||||
if resp[1] != 0x00:
|
||||
raise RuntimeError("Couldn't cancel I2C")
|
||||
if resp[2] == 0x10:
|
||||
# bus release will need "a few hundred microseconds"
|
||||
time.sleep(0.001)
|
||||
|
||||
# pylint: disable=too-many-arguments
|
||||
def _i2c_write(self, cmd, address, buffer, start=0, end=None):
|
||||
if self._i2c_state() != 0x00:
|
||||
self._i2c_cancel()
|
||||
|
|
@ -174,18 +186,19 @@ class MCP2221:
|
|||
while (end - start) > 0:
|
||||
chunk = min(end - start, MCP2221_MAX_I2C_DATA_LEN)
|
||||
# write out current chunk
|
||||
resp = self._hid_xfer(bytes([cmd,
|
||||
length & 0xFF,
|
||||
(length >> 8) & 0xFF,
|
||||
address << 1]) +
|
||||
buffer[start:(start+chunk)])
|
||||
resp = self._hid_xfer(
|
||||
bytes([cmd, length & 0xFF, (length >> 8) & 0xFF, address << 1])
|
||||
+ buffer[start : (start + chunk)]
|
||||
)
|
||||
# check for success
|
||||
if resp[1] != 0x00:
|
||||
if resp[2] in (RESP_I2C_START_TOUT,
|
||||
if resp[2] in (
|
||||
RESP_I2C_START_TOUT,
|
||||
RESP_I2C_WRADDRL_TOUT,
|
||||
RESP_I2C_WRADDRL_NACK,
|
||||
RESP_I2C_WRDATA_TOUT,
|
||||
RESP_I2C_STOP_TOUT):
|
||||
RESP_I2C_STOP_TOUT,
|
||||
):
|
||||
raise RuntimeError("Unrecoverable I2C state failure")
|
||||
retries += 1
|
||||
if retries >= MCP2221_RETRY_MAX:
|
||||
|
|
@ -208,11 +221,13 @@ class MCP2221:
|
|||
break
|
||||
if usb_cmd_status == RESP_I2C_WRITINGNOSTOP and cmd == 0x94:
|
||||
break # this is OK too!
|
||||
if usb_cmd_status in (RESP_I2C_START_TOUT,
|
||||
if usb_cmd_status in (
|
||||
RESP_I2C_START_TOUT,
|
||||
RESP_I2C_WRADDRL_TOUT,
|
||||
RESP_I2C_WRADDRL_NACK,
|
||||
RESP_I2C_WRDATA_TOUT,
|
||||
RESP_I2C_STOP_TOUT):
|
||||
RESP_I2C_STOP_TOUT,
|
||||
):
|
||||
raise RuntimeError("Unrecoverable I2C state failure")
|
||||
time.sleep(0.001)
|
||||
else:
|
||||
|
|
@ -227,10 +242,9 @@ class MCP2221:
|
|||
length = end - start
|
||||
|
||||
# tell it we want to read
|
||||
resp = self._hid_xfer(bytes([cmd,
|
||||
length & 0xFF,
|
||||
(length >> 8) & 0xFF,
|
||||
(address << 1) | 0x01]))
|
||||
resp = self._hid_xfer(
|
||||
bytes([cmd, length & 0xFF, (length >> 8) & 0xFF, (address << 1) | 0x01])
|
||||
)
|
||||
|
||||
# check for success
|
||||
if resp[1] != 0x00:
|
||||
|
|
@ -240,7 +254,7 @@ class MCP2221:
|
|||
while (end - start) > 0:
|
||||
for retry in range(MCP2221_RETRY_MAX):
|
||||
# the actual read
|
||||
resp = self._hid_xfer(b'\x40')
|
||||
resp = self._hid_xfer(b"\x40")
|
||||
# check for success
|
||||
if resp[1] == RESP_I2C_PARTIALDATA:
|
||||
time.sleep(0.001)
|
||||
|
|
@ -263,31 +277,54 @@ class MCP2221:
|
|||
buffer[k] = resp[4 + i]
|
||||
start += chunk
|
||||
|
||||
# pylint: enable=too-many-arguments
|
||||
|
||||
def i2c_configure(self, baudrate=100000):
|
||||
self._hid_xfer(bytes([0x10, # set parameters
|
||||
"""Configure I2C"""
|
||||
self._hid_xfer(
|
||||
bytes(
|
||||
[
|
||||
0x10, # set parameters
|
||||
0x00, # don't care
|
||||
0x00, # no effect
|
||||
0x20, # next byte is clock divider
|
||||
12000000 // baudrate - 3]))
|
||||
12000000 // baudrate - 3,
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
def i2c_writeto(self, address, buffer, *, start=0, end=None):
|
||||
"""Write data from the buffer to an address"""
|
||||
self._i2c_write(0x90, address, buffer, start, end)
|
||||
|
||||
def i2c_readfrom_into(self, address, buffer, *, start=0, end=None):
|
||||
"""Read data from an address and into the buffer"""
|
||||
self._i2c_read(0x91, address, buffer, start, end)
|
||||
|
||||
def i2c_writeto_then_readfrom(self, address, out_buffer, in_buffer, *,
|
||||
out_start=0, out_end=None,
|
||||
in_start=0, in_end=None):
|
||||
def i2c_writeto_then_readfrom(
|
||||
self,
|
||||
address,
|
||||
out_buffer,
|
||||
in_buffer,
|
||||
*,
|
||||
out_start=0,
|
||||
out_end=None,
|
||||
in_start=0,
|
||||
in_end=None
|
||||
):
|
||||
"""Write data from buffer_out to an address and then
|
||||
read data from an address and into buffer_in
|
||||
"""
|
||||
self._i2c_write(0x94, address, out_buffer, out_start, out_end)
|
||||
self._i2c_read(0x93, address, in_buffer, in_start, in_end)
|
||||
|
||||
def i2c_scan(self, *, start=0, end=0x79):
|
||||
"""Perform an I2C Device Scan"""
|
||||
found = []
|
||||
for addr in range(start, end + 1):
|
||||
# try a write
|
||||
try:
|
||||
self.i2c_writeto(addr, b'\x00')
|
||||
self.i2c_writeto(addr, b"\x00")
|
||||
except RuntimeError: # no reply!
|
||||
continue
|
||||
# store if success
|
||||
|
|
@ -298,25 +335,33 @@ class MCP2221:
|
|||
# ADC
|
||||
# ----------------------------------------------------------------
|
||||
def adc_configure(self, vref=0):
|
||||
report = bytearray(b'\x60'+b'\x00'*63)
|
||||
"""Configure the Analog-to-Digital Converter"""
|
||||
report = bytearray(b"\x60" + b"\x00" * 63)
|
||||
report[5] = 1 << 7 | (vref & 0b111)
|
||||
self._hid_xfer(report)
|
||||
|
||||
def adc_read(self, pin):
|
||||
resp = self._hid_xfer(b'\x10')
|
||||
"""Read from the Analog-to-Digital Converter"""
|
||||
resp = self._hid_xfer(b"\x10")
|
||||
return resp[49 + 2 * pin] << 8 | resp[48 + 2 * pin]
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# DAC
|
||||
# ----------------------------------------------------------------
|
||||
def dac_configure(self, vref=0):
|
||||
report = bytearray(b'\x60'+b'\x00'*63)
|
||||
"""Configure the Digital-to-Analog Converter"""
|
||||
report = bytearray(b"\x60" + b"\x00" * 63)
|
||||
report[3] = 1 << 7 | (vref & 0b111)
|
||||
self._hid_xfer(report)
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def dac_write(self, pin, value):
|
||||
report = bytearray(b'\x60'+b'\x00'*63)
|
||||
"""Write to the Digital-to-Analog Converter"""
|
||||
report = bytearray(b"\x60" + b"\x00" * 63)
|
||||
report[4] = 1 << 7 | (value & 0b11111)
|
||||
self._hid_xfer(report)
|
||||
|
||||
# pylint: enable=unused-argument
|
||||
|
||||
|
||||
mcp2221 = MCP2221()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
"""MCP2221 pin names"""
|
||||
from .mcp2221 import mcp2221
|
||||
|
||||
|
||||
class Pin:
|
||||
"""A basic Pin class for use with MCP2221."""
|
||||
|
||||
|
|
@ -17,6 +19,7 @@ class Pin:
|
|||
self._mode = None
|
||||
|
||||
def init(self, mode=IN, pull=None):
|
||||
"""Initialize the Pin"""
|
||||
if self.id is None:
|
||||
raise RuntimeError("Can not init a None type pin.")
|
||||
if mode in (Pin.IN, Pin.OUT):
|
||||
|
|
@ -40,35 +43,36 @@ class Pin:
|
|||
self._mode = mode
|
||||
|
||||
def value(self, val=None):
|
||||
"""Set or return the Pin Value"""
|
||||
# Digital In / Out
|
||||
if self._mode in (Pin.IN, Pin.OUT):
|
||||
# digital read
|
||||
if val is None:
|
||||
return mcp2221.gpio_get_pin(self.id)
|
||||
# digital write
|
||||
elif val in (Pin.LOW, Pin.HIGH):
|
||||
if val in (Pin.LOW, Pin.HIGH):
|
||||
mcp2221.gpio_set_pin(self.id, val)
|
||||
return None
|
||||
# nope
|
||||
else:
|
||||
raise ValueError("Invalid value for pin.")
|
||||
# Analog In
|
||||
elif self._mode == Pin.ADC:
|
||||
if self._mode == Pin.ADC:
|
||||
if val is None:
|
||||
# MCP2221 ADC is 10 bit, scale to 16 bit per CP API
|
||||
return mcp2221.adc_read(self.id) * 64
|
||||
else:
|
||||
# read only
|
||||
raise AttributeError("'AnalogIn' object has no attribute 'value'")
|
||||
# Analog Out
|
||||
elif self._mode == Pin.DAC:
|
||||
if self._mode == Pin.DAC:
|
||||
if val is None:
|
||||
# write only
|
||||
raise AttributeError("unreadable attribute")
|
||||
else:
|
||||
# scale 16 bit value to MCP2221 5 bit DAC (yes 5 bit)
|
||||
mcp2221.dac_write(self.id, val // 2048)
|
||||
else:
|
||||
raise RuntimeError("No action for mode {} with value {}".format(self._mode, val))
|
||||
return None
|
||||
raise RuntimeError(
|
||||
"No action for mode {} with value {}".format(self._mode, val)
|
||||
)
|
||||
|
||||
|
||||
# create pin instances for each pin
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
"""MIPS 24kec pin names"""
|
||||
from adafruit_blinka.microcontroller.generic_linux.periphery_pin import Pin
|
||||
|
||||
GPIO0 = Pin(0)
|
||||
|
|
@ -53,14 +54,10 @@ I2C0_SDA = GPIO4
|
|||
I2C0_SCL = GPIO5
|
||||
|
||||
# ordered as i2cId, sclId, sdaId
|
||||
i2cPorts = (
|
||||
(0, I2C0_SCL, I2C0_SDA),
|
||||
)
|
||||
i2cPorts = ((0, I2C0_SCL, I2C0_SDA),)
|
||||
|
||||
# ordered as spiId, sckId, mosiId, misoId
|
||||
spiPorts = (
|
||||
((0, 1), SPI0_SCLK, SPI0_MOSI, SPI0_MISO),
|
||||
)
|
||||
spiPorts = (((0, 1), SPI0_SCLK, SPI0_MOSI, SPI0_MISO),)
|
||||
|
||||
# ordered as uartId, txId, rxId
|
||||
uartPorts = (
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
"""Generic Connection class for Binho Nova to keep track of connection"""
|
||||
|
||||
|
||||
class Connection:
|
||||
"""Connection class"""
|
||||
|
||||
__instance = None
|
||||
|
||||
@staticmethod
|
||||
def getInstance():
|
||||
""" Static access method. """
|
||||
|
|
@ -12,13 +18,16 @@ class Connection:
|
|||
if Connection.__instance is not None:
|
||||
raise Exception("This class is a singleton!")
|
||||
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from binhoHostAdapter import binhoHostAdapter
|
||||
from binhoHostAdapter import binhoUtilities
|
||||
|
||||
# pylint: enable=import-outside-toplevel
|
||||
|
||||
utilities = binhoUtilities.binhoUtilities()
|
||||
devices = utilities.listAvailableDevices()
|
||||
|
||||
if len(devices) > 0:
|
||||
Connection.__instance = binhoHostAdapter.binhoHostAdapter(devices[0])
|
||||
else:
|
||||
raise RuntimeError('No Binho Nova found!')
|
||||
raise RuntimeError("No Binho Nova found!")
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
"""I2C Class for Binho Nova"""
|
||||
|
||||
from adafruit_blinka.microcontroller.nova import Connection
|
||||
|
||||
|
||||
class I2C:
|
||||
"""Custom I2C Class for Binho Nova"""
|
||||
|
||||
def __init__(self, *, frequency=400000):
|
||||
from adafruit_blinka.microcontroller.nova import Connection
|
||||
self._nova = Connection.getInstance()
|
||||
self._nova.setNumericalBase(10)
|
||||
self._nova.setOperationMode(0, "I2C")
|
||||
|
|
@ -9,7 +14,7 @@ class I2C:
|
|||
self._nova.setClockI2C(0, frequency)
|
||||
|
||||
def scan(self):
|
||||
|
||||
"""Perform an I2C Device Scan"""
|
||||
scanResults = []
|
||||
|
||||
for i in range(8, 121):
|
||||
|
|
@ -17,13 +22,13 @@ class I2C:
|
|||
|
||||
resp = result.split(" ")
|
||||
|
||||
if resp[3] == 'OK':
|
||||
if resp[3] == "OK":
|
||||
scanResults.append(i)
|
||||
|
||||
return scanResults
|
||||
|
||||
def writeto(self, address, buffer, *, start=0, end=None, stop=True):
|
||||
|
||||
"""Write data from the buffer to an address"""
|
||||
end = end if end else len(buffer)
|
||||
|
||||
self._nova.startI2C(0, address << 1)
|
||||
|
|
@ -37,7 +42,7 @@ class I2C:
|
|||
self._nova.endI2C(0, True)
|
||||
|
||||
def readfrom_into(self, address, buffer, *, start=0, end=None, stop=True):
|
||||
|
||||
"""Read data from an address and into the buffer"""
|
||||
end = end if end else len(buffer)
|
||||
|
||||
result = self._nova.readBytesI2C(0, address << 1, len(buffer[start:end]))
|
||||
|
|
@ -48,12 +53,26 @@ class I2C:
|
|||
for i in range(len(buffer[start:end])):
|
||||
buffer[start + i] = int(resp[2 + i])
|
||||
else:
|
||||
raise RuntimeError("Received error response from Binho Nova, result = " + result)
|
||||
|
||||
def writeto_then_readfrom(self, address, buffer_out, buffer_in, *,
|
||||
out_start=0, out_end=None,
|
||||
in_start=0, in_end=None, stop=False):
|
||||
raise RuntimeError(
|
||||
"Received error response from Binho Nova, result = " + result
|
||||
)
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def writeto_then_readfrom(
|
||||
self,
|
||||
address,
|
||||
buffer_out,
|
||||
buffer_in,
|
||||
*,
|
||||
out_start=0,
|
||||
out_end=None,
|
||||
in_start=0,
|
||||
in_end=None,
|
||||
stop=False
|
||||
):
|
||||
"""Write data from buffer_out to an address and then
|
||||
read data from an address and into buffer_in
|
||||
"""
|
||||
out_end = out_end if out_end else len(buffer_out)
|
||||
in_end = in_end if in_end else len(buffer_in)
|
||||
|
||||
|
|
@ -64,7 +83,9 @@ class I2C:
|
|||
|
||||
self._nova.endI2C(0, True)
|
||||
|
||||
result = self._nova.readBytesI2C(0, address<<1, len(buffer_in[in_start:in_end]))
|
||||
result = self._nova.readBytesI2C(
|
||||
0, address << 1, len(buffer_in[in_start:in_end])
|
||||
)
|
||||
|
||||
if result != "-NG":
|
||||
resp = result.split(" ")
|
||||
|
|
@ -72,4 +93,9 @@ class I2C:
|
|||
for i in range(len(buffer_in[in_start:in_end])):
|
||||
buffer_in[in_start + i] = int(resp[2 + i])
|
||||
else:
|
||||
raise RuntimeError("Received error response from Binho Nova, result = " + result)
|
||||
raise RuntimeError(
|
||||
"Received error response from Binho Nova, result = " + result
|
||||
)
|
||||
|
||||
|
||||
# pylint: enable=unused-argument
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
"""Binho Nova pin names"""
|
||||
|
||||
|
||||
class Pin:
|
||||
"""A basic Pin class for use with Binho Nova."""
|
||||
|
||||
IN = 'DIN'
|
||||
OUT = 'DOUT'
|
||||
AIN = 'AIN'
|
||||
AOUT = 'AOUT'
|
||||
PWM = 'PWM'
|
||||
IN = "DIN"
|
||||
OUT = "DOUT"
|
||||
AIN = "AIN"
|
||||
AOUT = "AOUT"
|
||||
PWM = "PWM"
|
||||
LOW = 0
|
||||
HIGH = 1
|
||||
|
||||
|
|
@ -13,7 +16,11 @@ class Pin:
|
|||
|
||||
def __init__(self, pin_id=None):
|
||||
if not Pin._nova:
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from adafruit_blinka.microcontroller.nova import Connection
|
||||
|
||||
# pylint: enable=import-outside-toplevel
|
||||
|
||||
Pin._nova = Connection.getInstance()
|
||||
# check if pin is valid
|
||||
if pin_id > 4:
|
||||
|
|
@ -22,6 +29,7 @@ class Pin:
|
|||
self.id = pin_id
|
||||
|
||||
def init(self, mode=IN, pull=None):
|
||||
"""Initialize the Pin"""
|
||||
if self.id is None:
|
||||
raise RuntimeError("Can not init a None type pin.")
|
||||
# Nova does't have configurable internal pulls for
|
||||
|
|
@ -30,17 +38,19 @@ class Pin:
|
|||
Pin._nova.setIOpinMode(self.id, mode)
|
||||
|
||||
def value(self, val=None):
|
||||
"""Set or return the Pin Value"""
|
||||
if self.id is None:
|
||||
raise RuntimeError("Can not access a None type pin.")
|
||||
# read
|
||||
if val is None:
|
||||
return int(Pin._nova.getIOpinValue(self.id).split('VALUE ')[1])
|
||||
return int(Pin._nova.getIOpinValue(self.id).split("VALUE ")[1])
|
||||
# write
|
||||
if val in (self.LOW, self.HIGH):
|
||||
Pin._nova.setIOpinValue(self.id, val)
|
||||
else:
|
||||
return None
|
||||
raise RuntimeError("Invalid value for pin")
|
||||
|
||||
|
||||
# create pin instances for each pin
|
||||
IO0 = Pin(0)
|
||||
IO1 = Pin(1)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
"""PWMOut Class for Binho Nova"""
|
||||
|
||||
try:
|
||||
from microcontroller.pin import pwmOuts
|
||||
|
|
@ -6,12 +7,20 @@ except ImportError:
|
|||
|
||||
from microcontroller.pin import Pin
|
||||
|
||||
|
||||
# pylint: disable=unnecessary-pass
|
||||
class PWMError(IOError):
|
||||
"""Base class for PWM errors."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class PWMOut(object):
|
||||
# pylint: enable=unnecessary-pass
|
||||
|
||||
|
||||
class PWMOut:
|
||||
"""Pulse Width Modulation Output Class"""
|
||||
|
||||
# Nova instance
|
||||
_nova = None
|
||||
MAX_CYCLE_LEVEL = 1024
|
||||
|
|
@ -36,11 +45,17 @@ class PWMOut(object):
|
|||
|
||||
"""
|
||||
if PWMOut._nova is None:
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from adafruit_blinka.microcontroller.nova import Connection
|
||||
|
||||
# pylint: enable=import-outside-toplevel
|
||||
|
||||
PWMOut._nova = Connection.getInstance()
|
||||
|
||||
PWMOut._nova.setOperationMode(0, 'IO')
|
||||
PWMOut._nova.setOperationMode(0, "IO")
|
||||
self._pwmpin = None
|
||||
self._channel = None
|
||||
self._enable = False
|
||||
self._open(pin, duty_cycle, frequency, variable_frequency)
|
||||
|
||||
def __del__(self):
|
||||
|
|
@ -76,8 +91,9 @@ class PWMOut(object):
|
|||
self._set_enabled(True)
|
||||
|
||||
def deinit(self):
|
||||
try:
|
||||
"""Deinit the Nova PWM."""
|
||||
# pylint: disable=broad-except
|
||||
try:
|
||||
if self._channel is not None:
|
||||
# self.duty_cycle = 0
|
||||
self._set_enabled(False) # make to disable before unexport
|
||||
|
|
@ -86,15 +102,22 @@ class PWMOut(object):
|
|||
# due to a race condition for which I have not yet been
|
||||
# able to find the root cause, deinit() often fails
|
||||
# but it does not effect future usage of the pwm pin
|
||||
print("warning: failed to deinitialize pwm pin {0}:{1} due to: {2}\n".format(self._channel, self._pwmpin, type(e).__name__))
|
||||
print(
|
||||
"warning: failed to deinitialize pwm pin {0}:{1} due to: {2}\n".format(
|
||||
self._channel, self._pwmpin, type(e).__name__
|
||||
)
|
||||
)
|
||||
finally:
|
||||
self._channel = None
|
||||
self._pwmpin = None
|
||||
# pylint: enable=broad-except
|
||||
|
||||
def _is_deinited(self):
|
||||
if self._pwmpin is None:
|
||||
raise ValueError("Object has been deinitialize and can no longer "
|
||||
"be used. Create a new object.")
|
||||
raise ValueError(
|
||||
"Object has been deinitialize and can no longer "
|
||||
"be used. Create a new object."
|
||||
)
|
||||
|
||||
# Mutable properties
|
||||
|
||||
|
|
@ -141,7 +164,9 @@ class PWMOut(object):
|
|||
duty_cycle = duty_cycle * PWMOut.MAX_CYCLE_LEVEL
|
||||
|
||||
# Set duty cycle
|
||||
# pylint: disable=protected-access
|
||||
Pin._nova.setIOpinValue(self._pwmpin, duty_cycle)
|
||||
# pylint: enable=protected-access
|
||||
|
||||
duty_cycle = property(_get_duty_cycle, _set_duty_cycle)
|
||||
"""Get or set the PWM's output duty cycle as a ratio from 0.0 to 1.0.
|
||||
|
|
@ -155,7 +180,7 @@ class PWMOut(object):
|
|||
"""
|
||||
|
||||
def _get_frequency(self):
|
||||
return int(PWMOut._nova.getIOpinPWMFreq(self._pwmpin).split('PWMFREQ ')[1])
|
||||
return int(PWMOut._nova.getIOpinPWMFreq(self._pwmpin).split("PWMFREQ ")[1])
|
||||
|
||||
def _set_frequency(self, frequency):
|
||||
if not isinstance(frequency, (int, float)):
|
||||
|
|
@ -178,17 +203,12 @@ class PWMOut(object):
|
|||
|
||||
if enabled == "1":
|
||||
return True
|
||||
elif enabled == "0":
|
||||
if enabled == "0":
|
||||
return False
|
||||
|
||||
raise PWMError(None, "Unknown enabled value: \"%s\"" % enabled)
|
||||
raise PWMError(None, 'Unknown enabled value: "%s"' % enabled)
|
||||
|
||||
def _set_enabled(self, value):
|
||||
if not isinstance(value, bool):
|
||||
raise TypeError("Invalid enabled type, should be string.")
|
||||
self._enable = value
|
||||
if not self._enable:
|
||||
self._set_duty_cycle(0.0)
|
||||
"""Get or set the PWM's output enabled state.
|
||||
|
||||
Raises:
|
||||
|
|
@ -197,9 +217,18 @@ class PWMOut(object):
|
|||
|
||||
:type: bool
|
||||
"""
|
||||
if not isinstance(value, bool):
|
||||
raise TypeError("Invalid enabled type, should be string.")
|
||||
self._enable = value
|
||||
if not self._enable:
|
||||
self._set_duty_cycle(0.0)
|
||||
|
||||
# String representation
|
||||
|
||||
def __str__(self):
|
||||
return "PWM%d, pin %s (freq=%f Hz, duty_cycle=%f%%)" % \
|
||||
(self._pin, self._pin, self.frequency, self.duty_cycle * 100,)
|
||||
return "PWM%d, pin %s (freq=%f Hz, duty_cycle=%f%%)" % (
|
||||
self._pin,
|
||||
self._pin,
|
||||
self.frequency,
|
||||
self.duty_cycle * 100,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,16 +1,21 @@
|
|||
"""SPI Class for Binho Nova"""
|
||||
from adafruit_blinka.microcontroller.nova import Connection
|
||||
|
||||
|
||||
class SPI:
|
||||
"""Custom SPI Class for Binho Nova"""
|
||||
|
||||
MSB = 0
|
||||
PAYLOAD_MAX_LENGTH = 64
|
||||
|
||||
def __init__(self, clock):
|
||||
from adafruit_blinka.microcontroller.nova import Connection
|
||||
self._nova = Connection.getInstance()
|
||||
self._nova.setNumericalBase(10)
|
||||
self._nova.setOperationMode(0, 'SPI')
|
||||
self._nova.setOperationMode(0, "SPI")
|
||||
self._nova.setClockSPI(0, clock)
|
||||
self._nova.setModeSPI(0, 0)
|
||||
self._nova.setIOpinMode(0, 'DOUT')
|
||||
self._nova.setIOpinMode(1, 'DOUT')
|
||||
self._nova.setIOpinMode(0, "DOUT")
|
||||
self._nova.setIOpinMode(1, "DOUT")
|
||||
self._nova.beginSPI(0)
|
||||
|
||||
# Cpol and Cpha set by mode
|
||||
|
|
@ -20,22 +25,38 @@ class SPI:
|
|||
# 2 1 0
|
||||
# 3 1 1
|
||||
|
||||
def init(self, baudrate=100000, polarity=0, phase=0, bits=8,
|
||||
firstbit=MSB, sck=None, mosi=None, miso=None):
|
||||
# pylint: disable=too-many-arguments,unused-argument
|
||||
def init(
|
||||
self,
|
||||
baudrate=100000,
|
||||
polarity=0,
|
||||
phase=0,
|
||||
bits=8,
|
||||
firstbit=MSB,
|
||||
sck=None,
|
||||
mosi=None,
|
||||
miso=None,
|
||||
):
|
||||
"""Initialize the Port"""
|
||||
# print("baudrate: " + str(baudrate))
|
||||
# print("mode: " + str((polarity<<1) | (phase)))
|
||||
self._nova.setClockSPI(0, baudrate)
|
||||
self._nova.setModeSPI(0, (polarity << 1) | (phase))
|
||||
|
||||
# pylint: enable=too-many-arguments,unused-argument
|
||||
|
||||
@staticmethod
|
||||
def get_received_data(lineOutput):
|
||||
return (lineOutput.split('RXD ')[1])
|
||||
"""Return any received data"""
|
||||
return lineOutput.split("RXD ")[1]
|
||||
|
||||
@property
|
||||
def frequency(self):
|
||||
return self._nova.getClockSPI(0).split('CLK ')[1]
|
||||
"""Return the current frequency"""
|
||||
return self._nova.getClockSPI(0).split("CLK ")[1]
|
||||
|
||||
def write(self, buf, start=0, end=None):
|
||||
"""Write data from the buffer to SPI"""
|
||||
end = end if end else len(buf)
|
||||
chunks, rest = divmod(end - start, self.PAYLOAD_MAX_LENGTH)
|
||||
for i in range(chunks):
|
||||
|
|
@ -52,11 +73,20 @@ class SPI:
|
|||
self._nova.transferBufferSPI(0, rest)
|
||||
|
||||
def readinto(self, buf, start=0, end=None, write_value=0):
|
||||
"""Read data from SPI and into the buffer"""
|
||||
end = end if end else len(buf)
|
||||
for i in range(start, end):
|
||||
buf[start+i] = int(self.get_received_data(self._nova.transferSPI(0, write_value)))
|
||||
buf[start + i] = int(
|
||||
self.get_received_data(self._nova.transferSPI(0, write_value))
|
||||
)
|
||||
|
||||
def write_readinto(self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None):
|
||||
# pylint: disable=too-many-arguments
|
||||
def write_readinto(
|
||||
self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
|
||||
):
|
||||
"""Perform a half-duplex write from buffer_out and then
|
||||
read data into buffer_in
|
||||
"""
|
||||
out_end = out_end if out_end else len(buffer_out)
|
||||
in_end = in_end if in_end else len(buffer_in)
|
||||
readlen = in_end - in_start
|
||||
|
|
@ -72,3 +102,5 @@ class SPI:
|
|||
if i < readlen:
|
||||
buffer_in[in_start + i] = data_in
|
||||
i += 1
|
||||
|
||||
# pylint: enable=too-many-arguments
|
||||
|
|
|
|||
|
|
@ -1,8 +1,16 @@
|
|||
import time
|
||||
"""UART Class for Binho Nova"""
|
||||
|
||||
from adafruit_blinka.microcontroller.nova import Connection
|
||||
|
||||
|
||||
class UART:
|
||||
"""Custom UART Class for Binho Nova"""
|
||||
|
||||
class UART():
|
||||
ESCAPE_SEQUENCE = "+++UART0"
|
||||
def __init__(self,
|
||||
|
||||
# pylint: disable=too-many-arguments
|
||||
def __init__(
|
||||
self,
|
||||
portid,
|
||||
baudrate=9600,
|
||||
bits=8,
|
||||
|
|
@ -10,8 +18,8 @@ class UART():
|
|||
stop=1,
|
||||
timeout=1000,
|
||||
read_buf_len=None,
|
||||
flow=None):
|
||||
from adafruit_blinka.microcontroller.nova import Connection
|
||||
flow=None,
|
||||
):
|
||||
self._nova = Connection.getInstance()
|
||||
|
||||
self._id = portid
|
||||
|
|
@ -23,10 +31,10 @@ class UART():
|
|||
|
||||
if flow is not None: # default 0
|
||||
raise NotImplementedError(
|
||||
"Parameter '{}' unsupported on Binho Nova".format(
|
||||
"flow"))
|
||||
"Parameter '{}' unsupported on Binho Nova".format("flow")
|
||||
)
|
||||
|
||||
self._nova.setOperationMode(self._id, 'UART')
|
||||
self._nova.setOperationMode(self._id, "UART")
|
||||
self._nova.setBaudRateUART(self._id, baudrate)
|
||||
self._nova.setDataBitsUART(self._id, bits)
|
||||
self._nova.setParityUART(self._id, parity)
|
||||
|
|
@ -34,32 +42,39 @@ class UART():
|
|||
self._nova.setEscapeSequenceUART(self._id, UART.ESCAPE_SEQUENCE)
|
||||
self._nova.beginBridgeUART(self._id)
|
||||
|
||||
# pylint: enable=too-many-arguments
|
||||
|
||||
def deinit(self):
|
||||
"""Deinitialize"""
|
||||
self._nova.writeBridgeUART(UART.ESCAPE_SEQUENCE)
|
||||
self._nova.stopBridgeUART(UART.ESCAPE_SEQUENCE)
|
||||
|
||||
def read(self, nbytes=None):
|
||||
"""Read data from UART and return it"""
|
||||
if nbytes is None:
|
||||
return None
|
||||
data = bytearray()
|
||||
for i in range(nbytes):
|
||||
for _ in range(nbytes):
|
||||
data.append(ord(self._nova.readBridgeUART()))
|
||||
return data
|
||||
|
||||
def readinto(self, buf, nbytes=None):
|
||||
"""Read data from UART and into the buffer"""
|
||||
if nbytes is None:
|
||||
return None
|
||||
for i in range(nbytes):
|
||||
for _ in range(nbytes):
|
||||
buf.append(ord(self._nova.readBridgeUART()))
|
||||
return buf
|
||||
|
||||
def readline(self):
|
||||
"""Read a single line of data from UART"""
|
||||
out = self._nova.readBridgeUART()
|
||||
line = out
|
||||
while out != '\r':
|
||||
while out != "\r":
|
||||
out = self._nova.readBridgeUART()
|
||||
line += out
|
||||
return line
|
||||
|
||||
def write(self, buf):
|
||||
"""Write data from the buffer to UART"""
|
||||
return self._nova.writeBridgeUART(buf)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
"""NXP IMX8M pin names"""
|
||||
from adafruit_blinka.microcontroller.generic_linux.libgpiod_pin import Pin
|
||||
|
||||
I2C2_SCL = Pin(144) # GPIO5_IO16
|
||||
|
|
@ -25,11 +26,18 @@ ECSPI1_SCLK = Pin(134) # GPIO5_IO6
|
|||
ECSPI1_SS0 = Pin(133) # GPIO5_IO9
|
||||
|
||||
|
||||
i2cPorts = ( (1, I2C2_SCL, I2C2_SDA), (2, I2C3_SCL, I2C3_SDA),)
|
||||
i2cPorts = (
|
||||
(1, I2C2_SCL, I2C2_SDA),
|
||||
(2, I2C3_SCL, I2C3_SDA),
|
||||
)
|
||||
# ordered as spiId, sckId, mosiId, misoId
|
||||
spiPorts = ((32766, ECSPI1_SCLK, ECSPI1_MOSI, ECSPI1_MISO),)
|
||||
# SysFS pwm outputs, pwm channel and pin in first tuple
|
||||
pwmOuts = ( ((0, 0), PWM1), ((1, 0), PWM2), ((2, 0), PWM3), )
|
||||
pwmOuts = (
|
||||
((0, 0), PWM1),
|
||||
((1, 0), PWM2),
|
||||
((2, 0), PWM3),
|
||||
)
|
||||
|
||||
# UART1_TXD/RXD on /dev/ttymxc0
|
||||
# UART3_TXD/RXD not available (?)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
"""Atmel SAMA5 pin names"""
|
||||
from adafruit_blinka.microcontroller.generic_linux.libgpiod_pin import Pin
|
||||
|
||||
PD23 = Pin(119)
|
||||
|
|
@ -45,4 +46,8 @@ spiPorts = ( (0, SPI0_SCLK, SPI0_MOSI, SPI0_MISO), )
|
|||
# ordered as uartId, txId, rxId
|
||||
uartPorts = ((1, UART1_TX, UART1_RX),)
|
||||
# SysFS pwm outputs, pwm channel and pin in first tuple
|
||||
pwmOuts = ( ((0, 1), PWM1), ((0, 2), PWM2), ((0, 3), PWM3), )
|
||||
pwmOuts = (
|
||||
((0, 1), PWM1),
|
||||
((0, 2), PWM2),
|
||||
((0, 3), PWM3),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
"""SnapDragon APQ8016 pin names"""
|
||||
from adafruit_blinka.microcontroller.generic_linux.libgpiod_pin import Pin
|
||||
|
||||
GPIO_0 = Pin((0, 0))
|
||||
|
|
@ -145,8 +146,14 @@ SPI0_MISO = GPIO_17
|
|||
SPI0_MOSI = GPIO_16
|
||||
SPI0_CS = GPIO_18
|
||||
|
||||
i2cPorts = ( (0, I2C0_SCL, I2C0_SDA), (1, I2C1_SCL, I2C1_SDA), )
|
||||
i2cPorts = (
|
||||
(0, I2C0_SCL, I2C0_SDA),
|
||||
(1, I2C1_SCL, I2C1_SDA),
|
||||
)
|
||||
# ordered as spiId, sckId, mosiId, misoId
|
||||
spiPorts = ((0, SPI0_SCLK, SPI0_MOSI, SPI0_MISO),)
|
||||
# ordered as uartId, txId, rxId
|
||||
uartPorts = ( (0, UART0_TX, UART0_RX), (1, UART1_TX, UART1_RX), )
|
||||
uartPorts = (
|
||||
(0, UART0_TX, UART0_RX),
|
||||
(1, UART1_TX, UART1_RX),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2,53 +2,53 @@
|
|||
|
||||
from microcontroller import Pin
|
||||
|
||||
A0 = Pin('A0')
|
||||
A1 = Pin('A1')
|
||||
A2 = Pin('A2')
|
||||
A3 = Pin('A3')
|
||||
A4 = Pin('A4')
|
||||
A5 = Pin('A5')
|
||||
A6 = Pin('A6')
|
||||
A7 = Pin('A7')
|
||||
A8 = Pin('A8')
|
||||
A9 = Pin('A9')
|
||||
A10 = Pin('A10')
|
||||
A11 = Pin('A11')
|
||||
A12 = Pin('A12')
|
||||
A13 = Pin('A13')
|
||||
A14 = Pin('A14')
|
||||
A15 = Pin('A15')
|
||||
B0 = Pin('B0')
|
||||
B1 = Pin('B1')
|
||||
B2 = Pin('B2')
|
||||
B3 = Pin('B3')
|
||||
B4 = Pin('B4')
|
||||
B5 = Pin('B5')
|
||||
B6 = Pin('B6')
|
||||
B7 = Pin('B7')
|
||||
B8 = Pin('B8')
|
||||
B9 = Pin('B9')
|
||||
B10 = Pin('B10')
|
||||
B11 = Pin('B11')
|
||||
B12 = Pin('B12')
|
||||
B13 = Pin('B13')
|
||||
B14 = Pin('B14')
|
||||
B15 = Pin('B15')
|
||||
C0 = Pin('C0')
|
||||
C1 = Pin('C1')
|
||||
C2 = Pin('C2')
|
||||
C3 = Pin('C3')
|
||||
C4 = Pin('C4')
|
||||
C5 = Pin('C5')
|
||||
C6 = Pin('C6')
|
||||
C7 = Pin('C7')
|
||||
C8 = Pin('C8')
|
||||
C9 = Pin('C9')
|
||||
C10 = Pin('C10')
|
||||
C11 = Pin('C11')
|
||||
C12 = Pin('C12')
|
||||
C13 = Pin('C13')
|
||||
D2 = Pin('D2')
|
||||
A0 = Pin("A0")
|
||||
A1 = Pin("A1")
|
||||
A2 = Pin("A2")
|
||||
A3 = Pin("A3")
|
||||
A4 = Pin("A4")
|
||||
A5 = Pin("A5")
|
||||
A6 = Pin("A6")
|
||||
A7 = Pin("A7")
|
||||
A8 = Pin("A8")
|
||||
A9 = Pin("A9")
|
||||
A10 = Pin("A10")
|
||||
A11 = Pin("A11")
|
||||
A12 = Pin("A12")
|
||||
A13 = Pin("A13")
|
||||
A14 = Pin("A14")
|
||||
A15 = Pin("A15")
|
||||
B0 = Pin("B0")
|
||||
B1 = Pin("B1")
|
||||
B2 = Pin("B2")
|
||||
B3 = Pin("B3")
|
||||
B4 = Pin("B4")
|
||||
B5 = Pin("B5")
|
||||
B6 = Pin("B6")
|
||||
B7 = Pin("B7")
|
||||
B8 = Pin("B8")
|
||||
B9 = Pin("B9")
|
||||
B10 = Pin("B10")
|
||||
B11 = Pin("B11")
|
||||
B12 = Pin("B12")
|
||||
B13 = Pin("B13")
|
||||
B14 = Pin("B14")
|
||||
B15 = Pin("B15")
|
||||
C0 = Pin("C0")
|
||||
C1 = Pin("C1")
|
||||
C2 = Pin("C2")
|
||||
C3 = Pin("C3")
|
||||
C4 = Pin("C4")
|
||||
C5 = Pin("C5")
|
||||
C6 = Pin("C6")
|
||||
C7 = Pin("C7")
|
||||
C8 = Pin("C8")
|
||||
C9 = Pin("C9")
|
||||
C10 = Pin("C10")
|
||||
C11 = Pin("C11")
|
||||
C12 = Pin("C12")
|
||||
C13 = Pin("C13")
|
||||
D2 = Pin("D2")
|
||||
|
||||
# ordered as spiId, sckId, mosiId, misoId
|
||||
SPI_PORTS = ((1, B13, B15, B14), (2, A5, A6, A7))
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
import sys
|
||||
"""Tegra T186 pin names"""
|
||||
|
||||
import atexit
|
||||
import Jetson.GPIO as GPIO
|
||||
|
||||
GPIO.setmode(GPIO.TEGRA_SOC)
|
||||
GPIO.setwarnings(False) # shh!
|
||||
|
||||
# Pins dont exist in CPython so...lets make our own!
|
||||
|
||||
class Pin:
|
||||
"""Pins dont exist in CPython so...lets make our own!"""
|
||||
|
||||
IN = 0
|
||||
OUT = 1
|
||||
LOW = 0
|
||||
|
|
@ -28,7 +32,8 @@ class Pin:
|
|||
return self.id == other
|
||||
|
||||
def init(self, mode=IN, pull=None):
|
||||
if mode != None:
|
||||
"""Initialize the Pin"""
|
||||
if mode is not None:
|
||||
if mode == self.IN:
|
||||
self._mode = self.IN
|
||||
GPIO.setup(self.id, GPIO.IN)
|
||||
|
|
@ -37,7 +42,7 @@ class Pin:
|
|||
GPIO.setup(self.id, GPIO.OUT)
|
||||
else:
|
||||
raise RuntimeError("Invalid mode for pin: %s" % self.id)
|
||||
if pull != None:
|
||||
if pull is not None:
|
||||
if self._mode != self.IN:
|
||||
raise RuntimeError("Cannot set pull resistor on output")
|
||||
if pull == self.PULL_UP:
|
||||
|
|
@ -48,53 +53,60 @@ class Pin:
|
|||
raise RuntimeError("Invalid pull for pin: %s" % self.id)
|
||||
|
||||
def value(self, val=None):
|
||||
if val != None:
|
||||
"""Set or return the Pin Value"""
|
||||
if val is not None:
|
||||
if val == self.LOW:
|
||||
self._value = val
|
||||
GPIO.output(self.id, val)
|
||||
elif val == self.HIGH:
|
||||
return None
|
||||
if val == self.HIGH:
|
||||
self._value = val
|
||||
GPIO.output(self.id, val)
|
||||
else:
|
||||
return None
|
||||
raise RuntimeError("Invalid value for pin")
|
||||
else:
|
||||
return GPIO.input(self.id)
|
||||
|
||||
# pylint: disable=no-method-argument
|
||||
@atexit.register
|
||||
def cleanup():
|
||||
"""Clean up pins"""
|
||||
print("Exiting... \nCleaning up pins")
|
||||
GPIO.cleanup()
|
||||
|
||||
# Cannot be used as GPIO
|
||||
SDA = Pin('GPIO_SEN9')
|
||||
SCL = Pin('GPIO_SEN8')
|
||||
SDA_1 = Pin('GEN1_I2C_SDA')
|
||||
SCL_1 = Pin('GEN1_I2C_SCL')
|
||||
# pylint: enable=no-method-argument
|
||||
|
||||
J04 = Pin('AUD_MCLK')
|
||||
J06 = Pin('GPIO_AUD1')
|
||||
AA02 = Pin('CAN_GPIO2')
|
||||
N06 = Pin('GPIO_CAM7')
|
||||
N04 = Pin('GPIO_CAM5')
|
||||
N05 = Pin('GPIO_CAM6')
|
||||
N03 = Pin('GPIO_CAM4')
|
||||
AA01 = Pin('CAN_GPIO1')
|
||||
I05 = Pin('GPIO_PQ5')
|
||||
T03 = Pin('UART1_CTS')
|
||||
T02 = Pin('UART1_RTS')
|
||||
J00 = Pin('DAP1_SCLK')
|
||||
J03 = Pin('DAP1_FS')
|
||||
J02 = Pin('DAP1_DIN')
|
||||
J01 = Pin('DAP1_DOUT')
|
||||
P17 = Pin('GPIO_EXP_P17')
|
||||
AA00 = Pin('CAN0_GPIO0')
|
||||
Y01 = Pin('GPIO_MDM2')
|
||||
P16 = Pin('GPIO_EXP_P16')
|
||||
I04 = Pin('GPIO_PQ4')
|
||||
J05 = Pin('GPIO_AUD0')
|
||||
|
||||
# Cannot be used as GPIO
|
||||
SDA = Pin("GPIO_SEN9")
|
||||
SCL = Pin("GPIO_SEN8")
|
||||
SDA_1 = Pin("GEN1_I2C_SDA")
|
||||
SCL_1 = Pin("GEN1_I2C_SCL")
|
||||
|
||||
J04 = Pin("AUD_MCLK")
|
||||
J06 = Pin("GPIO_AUD1")
|
||||
AA02 = Pin("CAN_GPIO2")
|
||||
N06 = Pin("GPIO_CAM7")
|
||||
N04 = Pin("GPIO_CAM5")
|
||||
N05 = Pin("GPIO_CAM6")
|
||||
N03 = Pin("GPIO_CAM4")
|
||||
AA01 = Pin("CAN_GPIO1")
|
||||
I05 = Pin("GPIO_PQ5")
|
||||
T03 = Pin("UART1_CTS")
|
||||
T02 = Pin("UART1_RTS")
|
||||
J00 = Pin("DAP1_SCLK")
|
||||
J03 = Pin("DAP1_FS")
|
||||
J02 = Pin("DAP1_DIN")
|
||||
J01 = Pin("DAP1_DOUT")
|
||||
P17 = Pin("GPIO_EXP_P17")
|
||||
AA00 = Pin("CAN0_GPIO0")
|
||||
Y01 = Pin("GPIO_MDM2")
|
||||
P16 = Pin("GPIO_EXP_P16")
|
||||
I04 = Pin("GPIO_PQ4")
|
||||
J05 = Pin("GPIO_AUD0")
|
||||
|
||||
i2cPorts = (
|
||||
(1, SCL, SDA), (0, SCL_1, SDA_1),
|
||||
(1, SCL, SDA),
|
||||
(0, SCL_1, SDA_1),
|
||||
)
|
||||
|
||||
# ordered as spiId, sckId, mosiId, misoId
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
import sys
|
||||
"""Tegra T194 pin names"""
|
||||
import atexit
|
||||
import Jetson.GPIO as GPIO
|
||||
|
||||
GPIO.setmode(GPIO.TEGRA_SOC)
|
||||
GPIO.setwarnings(False) # shh!
|
||||
|
||||
# Pins dont exist in CPython so...lets make our own!
|
||||
|
||||
class Pin:
|
||||
"""Pins dont exist in CPython so...lets make our own!"""
|
||||
|
||||
IN = 0
|
||||
OUT = 1
|
||||
LOW = 0
|
||||
|
|
@ -28,7 +31,8 @@ class Pin:
|
|||
return self.id == other
|
||||
|
||||
def init(self, mode=IN, pull=None):
|
||||
if mode != None:
|
||||
"""Initialize the Pin"""
|
||||
if mode is not None:
|
||||
if mode == self.IN:
|
||||
self._mode = self.IN
|
||||
GPIO.setup(self.id, GPIO.IN)
|
||||
|
|
@ -37,7 +41,7 @@ class Pin:
|
|||
GPIO.setup(self.id, GPIO.OUT)
|
||||
else:
|
||||
raise RuntimeError("Invalid mode for pin: %s" % self.id)
|
||||
if pull != None:
|
||||
if pull is not None:
|
||||
if self._mode != self.IN:
|
||||
raise RuntimeError("Cannot set pull resistor on output")
|
||||
if pull == self.PULL_UP:
|
||||
|
|
@ -48,72 +52,79 @@ class Pin:
|
|||
raise RuntimeError("Invalid pull for pin: %s" % self.id)
|
||||
|
||||
def value(self, val=None):
|
||||
if val != None:
|
||||
"""Set or return the Pin Value"""
|
||||
if val is not None:
|
||||
if val == self.LOW:
|
||||
self._value = val
|
||||
GPIO.output(self.id, val)
|
||||
elif val == self.HIGH:
|
||||
return None
|
||||
if val == self.HIGH:
|
||||
self._value = val
|
||||
GPIO.output(self.id, val)
|
||||
else:
|
||||
return None
|
||||
raise RuntimeError("Invalid value for pin")
|
||||
else:
|
||||
return GPIO.input(self.id)
|
||||
|
||||
# pylint: disable=no-method-argument
|
||||
@atexit.register
|
||||
def cleanup():
|
||||
"""Clean up pins"""
|
||||
print("Exiting... \nCleaning up pins")
|
||||
GPIO.cleanup()
|
||||
|
||||
# pylint: enable=no-method-argument
|
||||
|
||||
|
||||
# Cannot be used as GPIO
|
||||
SDA = Pin('DP_AUX_CH3_N')
|
||||
SCL = Pin('DP_AUX_CH3_P')
|
||||
SDA_1 = Pin('GEN2_I2C_SDA')
|
||||
SCL_1 = Pin('GEN2_I2C_SCL')
|
||||
SDA = Pin("DP_AUX_CH3_N")
|
||||
SCL = Pin("DP_AUX_CH3_P")
|
||||
SDA_1 = Pin("GEN2_I2C_SDA")
|
||||
SCL_1 = Pin("GEN2_I2C_SCL")
|
||||
|
||||
# Jetson Xavier only
|
||||
Q06 = Pin('SOC_GPIO42')
|
||||
AA03 = Pin('CAN0_DIN')
|
||||
AA02 = Pin('CAN0_DOUT')
|
||||
BB01 = Pin('CAN1_EN')
|
||||
AA00 = Pin('CAN1_DOUT')
|
||||
H07 = Pin('DAP2_SCLK')
|
||||
I02 = Pin('DAP2_FS')
|
||||
I01 = Pin('DAP2_DIN')
|
||||
I00 = Pin('DAP2_DOUT')
|
||||
BB00 = Pin('CAN1_STB')
|
||||
H00 = Pin('SOC_GPIO12')
|
||||
Q01 = Pin('SOC_GPIO21')
|
||||
AA01 = Pin('CAN1_DIN')
|
||||
Q06 = Pin("SOC_GPIO42")
|
||||
AA03 = Pin("CAN0_DIN")
|
||||
AA02 = Pin("CAN0_DOUT")
|
||||
BB01 = Pin("CAN1_EN")
|
||||
AA00 = Pin("CAN1_DOUT")
|
||||
H07 = Pin("DAP2_SCLK")
|
||||
I02 = Pin("DAP2_FS")
|
||||
I01 = Pin("DAP2_DIN")
|
||||
I00 = Pin("DAP2_DOUT")
|
||||
BB00 = Pin("CAN1_STB")
|
||||
H00 = Pin("SOC_GPIO12")
|
||||
Q01 = Pin("SOC_GPIO21")
|
||||
AA01 = Pin("CAN1_DIN")
|
||||
|
||||
# Jetson NX only
|
||||
S04 = Pin('AUD_MCLK')
|
||||
T05 = Pin('DAP5_SCLK')
|
||||
Y00 = Pin('SPI3_SCK')
|
||||
CC04 = Pin('TOUCH_CLK')
|
||||
Y04 = Pin('SPI3_CS1_N')
|
||||
Y03 = Pin('SPI3_CS0_N')
|
||||
Y01 = Pin('SPI3_MISO')
|
||||
Q05 = Pin('SOC_GPIO41')
|
||||
Q06 = Pin('SOC_GPIO42')
|
||||
U00 = Pin('DAP5_FS')
|
||||
Y02 = Pin('SPI3_MOSI')
|
||||
T07 = Pin('DAP5_DIN')
|
||||
T06 = Pin('DAP5_DOUT')
|
||||
S04 = Pin("AUD_MCLK")
|
||||
T05 = Pin("DAP5_SCLK")
|
||||
Y00 = Pin("SPI3_SCK")
|
||||
CC04 = Pin("TOUCH_CLK")
|
||||
Y04 = Pin("SPI3_CS1_N")
|
||||
Y03 = Pin("SPI3_CS0_N")
|
||||
Y01 = Pin("SPI3_MISO")
|
||||
Q05 = Pin("SOC_GPIO41")
|
||||
Q06 = Pin("SOC_GPIO42")
|
||||
U00 = Pin("DAP5_FS")
|
||||
Y02 = Pin("SPI3_MOSI")
|
||||
T07 = Pin("DAP5_DIN")
|
||||
T06 = Pin("DAP5_DOUT")
|
||||
|
||||
# Shared
|
||||
N01 = Pin('SOC_GPIO54')
|
||||
R00 = Pin('SOC_GPIO44')
|
||||
R04 = Pin('UART1_RTS')
|
||||
R05 = Pin('UART1_CTS')
|
||||
Z03 = Pin('SPI1_SCK')
|
||||
Z04 = Pin('SPI1_MISO')
|
||||
Z05 = Pin('SPI1_MOSI')
|
||||
Z06 = Pin('SPI1_CS0_N')
|
||||
Z07 = Pin('SPI1_CS1_N')
|
||||
N01 = Pin("SOC_GPIO54")
|
||||
R00 = Pin("SOC_GPIO44")
|
||||
R04 = Pin("UART1_RTS")
|
||||
R05 = Pin("UART1_CTS")
|
||||
Z03 = Pin("SPI1_SCK")
|
||||
Z04 = Pin("SPI1_MISO")
|
||||
Z05 = Pin("SPI1_MOSI")
|
||||
Z06 = Pin("SPI1_CS0_N")
|
||||
Z07 = Pin("SPI1_CS1_N")
|
||||
|
||||
i2cPorts = (
|
||||
(8, SCL, SDA), (1, SCL_1, SDA_1),
|
||||
(8, SCL, SDA),
|
||||
(1, SCL_1, SDA_1),
|
||||
)
|
||||
|
||||
# ordered as spiId, sckId, mosiId, misoId
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
import sys
|
||||
"""Tegra T210 pin names"""
|
||||
|
||||
import atexit
|
||||
import Jetson.GPIO as GPIO
|
||||
|
||||
GPIO.setmode(GPIO.TEGRA_SOC)
|
||||
GPIO.setwarnings(False) # shh!
|
||||
|
||||
# Pins dont exist in CPython so...lets make our own!
|
||||
|
||||
class Pin:
|
||||
"""Pins dont exist in CPython so...lets make our own!"""
|
||||
|
||||
IN = 0
|
||||
OUT = 1
|
||||
LOW = 0
|
||||
|
|
@ -28,7 +32,8 @@ class Pin:
|
|||
return self.id == other
|
||||
|
||||
def init(self, mode=IN, pull=None):
|
||||
if mode != None:
|
||||
"""Initialize the Pin"""
|
||||
if mode is not None:
|
||||
if mode == self.IN:
|
||||
self._mode = self.IN
|
||||
GPIO.setup(self.id, GPIO.IN)
|
||||
|
|
@ -37,7 +42,7 @@ class Pin:
|
|||
GPIO.setup(self.id, GPIO.OUT)
|
||||
else:
|
||||
raise RuntimeError("Invalid mode for pin: %s" % self.id)
|
||||
if pull != None:
|
||||
if pull is not None:
|
||||
if self._mode != self.IN:
|
||||
raise RuntimeError("Cannot set pull resistor on output")
|
||||
if pull == self.PULL_UP:
|
||||
|
|
@ -48,74 +53,81 @@ class Pin:
|
|||
raise RuntimeError("Invalid pull for pin: %s" % self.id)
|
||||
|
||||
def value(self, val=None):
|
||||
if val != None:
|
||||
"""Set or return the Pin Value"""
|
||||
if val is not None:
|
||||
if val == self.LOW:
|
||||
self._value = val
|
||||
GPIO.output(self.id, val)
|
||||
elif val == self.HIGH:
|
||||
return None
|
||||
if val == self.HIGH:
|
||||
self._value = val
|
||||
GPIO.output(self.id, val)
|
||||
else:
|
||||
return None
|
||||
raise RuntimeError("Invalid value for pin")
|
||||
else:
|
||||
return GPIO.input(self.id)
|
||||
|
||||
# pylint: disable=no-method-argument
|
||||
@atexit.register
|
||||
def cleanup():
|
||||
"""Clean up pins"""
|
||||
print("Exiting... \nCleaning up pins")
|
||||
GPIO.cleanup()
|
||||
|
||||
# pylint: enable=no-method-argument
|
||||
|
||||
|
||||
# Cannot be used as GPIO
|
||||
SDA = Pin('GEN1_I2C_SDA')
|
||||
SCL = Pin('GEN1_I2C_SCL')
|
||||
SDA_1 = Pin('GEN2_I2C_SDA')
|
||||
SCL_1 = Pin('GEN2_I2C_SCL')
|
||||
SDA = Pin("GEN1_I2C_SDA")
|
||||
SCL = Pin("GEN1_I2C_SCL")
|
||||
SDA_1 = Pin("GEN2_I2C_SDA")
|
||||
SCL_1 = Pin("GEN2_I2C_SCL")
|
||||
|
||||
# These pins are native to TX1
|
||||
BB03 = Pin('GPIO_X1_AUD')
|
||||
X02 = Pin('MOTION_INT')
|
||||
H07 = Pin('AP_WAKE_NFC')
|
||||
E04 = Pin('DMIC3_CLK')
|
||||
U03 = Pin('UART1_CTS')
|
||||
U02 = Pin('UART1_RTS')
|
||||
B03 = Pin('DAP1_SCLK')
|
||||
B00 = Pin('DAP1_FS')
|
||||
B01 = Pin('DAP1_DIN')
|
||||
B02 = Pin('DAP1_DOUT')
|
||||
P17 = Pin('GPIO_EXP_P17')
|
||||
E05 = Pin('DMIC3_DAT')
|
||||
X00 = Pin('MODEM_WAKE_AP')
|
||||
P16 = Pin('GPIO_EXP_P16')
|
||||
X03 = Pin('ALS_PROX_INT')
|
||||
BB03 = Pin("GPIO_X1_AUD")
|
||||
X02 = Pin("MOTION_INT")
|
||||
H07 = Pin("AP_WAKE_NFC")
|
||||
E04 = Pin("DMIC3_CLK")
|
||||
U03 = Pin("UART1_CTS")
|
||||
U02 = Pin("UART1_RTS")
|
||||
B03 = Pin("DAP1_SCLK")
|
||||
B00 = Pin("DAP1_FS")
|
||||
B01 = Pin("DAP1_DIN")
|
||||
B02 = Pin("DAP1_DOUT")
|
||||
P17 = Pin("GPIO_EXP_P17")
|
||||
E05 = Pin("DMIC3_DAT")
|
||||
X00 = Pin("MODEM_WAKE_AP")
|
||||
P16 = Pin("GPIO_EXP_P16")
|
||||
X03 = Pin("ALS_PROX_INT")
|
||||
|
||||
# These pins are native to NANO
|
||||
S05 = Pin('CAM_AF_EN')
|
||||
Z00 = Pin('GPIO_PZ0')
|
||||
V00 = Pin('LCD_BL_PW')
|
||||
G03 = Pin('UART2_CTS')
|
||||
G02 = Pin('UART2_RTS')
|
||||
J07 = Pin('DAP4_SCLK')
|
||||
J04 = Pin('DAP4_FS')
|
||||
J05 = Pin('DAP4_DIN')
|
||||
J06 = Pin('DAP4_DOUT')
|
||||
Y02 = Pin('LCD_TE')
|
||||
DD00 = Pin('SPI2_CS1')
|
||||
B07 = Pin('SPI2_CS0')
|
||||
B05 = Pin('SPI2_MISO')
|
||||
B04 = Pin('SPI2_MOSI')
|
||||
B06 = Pin('SPI2_SCK')
|
||||
S05 = Pin("CAM_AF_EN")
|
||||
Z00 = Pin("GPIO_PZ0")
|
||||
V00 = Pin("LCD_BL_PW")
|
||||
G03 = Pin("UART2_CTS")
|
||||
G02 = Pin("UART2_RTS")
|
||||
J07 = Pin("DAP4_SCLK")
|
||||
J04 = Pin("DAP4_FS")
|
||||
J05 = Pin("DAP4_DIN")
|
||||
J06 = Pin("DAP4_DOUT")
|
||||
Y02 = Pin("LCD_TE")
|
||||
DD00 = Pin("SPI2_CS1")
|
||||
B07 = Pin("SPI2_CS0")
|
||||
B05 = Pin("SPI2_MISO")
|
||||
B04 = Pin("SPI2_MOSI")
|
||||
B06 = Pin("SPI2_SCK")
|
||||
|
||||
# These pins are shared across T210
|
||||
BB00 = Pin('AUD_MCLK')
|
||||
C04 = Pin('SPI1_CS1')
|
||||
C03 = Pin('SPI1_CS0')
|
||||
C01 = Pin('SPI1_MISO')
|
||||
C00 = Pin('SPI1_MOSI')
|
||||
C02 = Pin('SPI1_SCK')
|
||||
E06 = Pin('GPIO_PE6')
|
||||
BB00 = Pin("AUD_MCLK")
|
||||
C04 = Pin("SPI1_CS1")
|
||||
C03 = Pin("SPI1_CS0")
|
||||
C01 = Pin("SPI1_MISO")
|
||||
C00 = Pin("SPI1_MOSI")
|
||||
C02 = Pin("SPI1_SCK")
|
||||
E06 = Pin("GPIO_PE6")
|
||||
|
||||
i2cPorts = (
|
||||
(0, SCL, SDA), (1, SCL_1, SDA_1),
|
||||
(0, SCL, SDA),
|
||||
(1, SCL_1, SDA_1),
|
||||
)
|
||||
|
||||
# ordered as spiId, sckId, mosiId, misoId
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ else:
|
|||
|
||||
from adafruit_blinka import ContextManaged
|
||||
|
||||
class AnalogIn(ContextManaged):
|
||||
|
||||
class AnalogIn(ContextManaged):
|
||||
def __init__(self, pin):
|
||||
self._pin = Pin(pin.id)
|
||||
self._pin.init(mode=Pin.ADC)
|
||||
|
|
@ -34,6 +34,7 @@ class AnalogIn(ContextManaged):
|
|||
def deinit(self):
|
||||
del self._pin
|
||||
|
||||
|
||||
class AnalogOut(ContextManaged):
|
||||
def __init__(self, pin):
|
||||
self._pin = Pin(pin.id)
|
||||
|
|
|
|||
|
|
@ -21,8 +21,11 @@ class I2C(Lockable):
|
|||
def init(self, scl, sda, frequency):
|
||||
from machine import Pin
|
||||
from machine import I2C as _I2C
|
||||
|
||||
self.deinit()
|
||||
id = -1 # force bitbanging implementation - in future introspect platform if SDA/SCL matches hardware I2C
|
||||
id = (
|
||||
-1
|
||||
) # force bitbanging implementation - in future introspect platform if SDA/SCL matches hardware I2C
|
||||
self._i2c = _I2C(id, Pin(scl.id), Pin(sda.id), freq=frequency)
|
||||
|
||||
def deinit(self):
|
||||
|
|
@ -61,11 +64,13 @@ class I2C(Lockable):
|
|||
class SPI(Lockable):
|
||||
def __init__(self, clock, MOSI=None, MISO=None):
|
||||
from machine import SPI
|
||||
|
||||
self._spi = SPI(-1)
|
||||
self._pins = (clock, MOSI, MISO)
|
||||
|
||||
def configure(self, baudrate=100000, polarity=0, phase=0, bits=8):
|
||||
from machine import SPI, Pin
|
||||
|
||||
if self._locked:
|
||||
# TODO verify if _spi obj 'caches' sck, mosi, miso to avoid storing in _attributeIds (duplicated in busio)
|
||||
# i.e. #init ignores MOSI=None rather than unsetting
|
||||
|
|
@ -77,7 +82,8 @@ class SPI(Lockable):
|
|||
firstbit=SPI.MSB,
|
||||
sck=Pin(self._pins[0].id),
|
||||
mosi=Pin(self._pins[1].id),
|
||||
miso=Pin(self._pins[2].id))
|
||||
miso=Pin(self._pins[2].id),
|
||||
)
|
||||
else:
|
||||
raise RuntimeError("First call try_lock()")
|
||||
|
||||
|
|
|
|||
|
|
@ -152,12 +152,16 @@ elif "sphinx" in sys.modules:
|
|||
else:
|
||||
raise NotImplementedError("Board not supported {}".format(board_id))
|
||||
|
||||
|
||||
def I2C():
|
||||
"""The singleton I2C interface"""
|
||||
import busio
|
||||
|
||||
return busio.I2C(SCL, SDA)
|
||||
|
||||
|
||||
def SPI():
|
||||
"""The singleton SPI interface"""
|
||||
import busio
|
||||
|
||||
return busio.SPI(SCLK, MOSI, MISO)
|
||||
|
|
|
|||
97
src/busio.py
97
src/busio.py
|
|
@ -14,6 +14,7 @@ from adafruit_blinka.agnostic import board_id, detector
|
|||
import adafruit_platformdetect.constants.boards as ap_board
|
||||
import adafruit_platformdetect.constants.chips as ap_chip
|
||||
|
||||
|
||||
class I2C(Lockable):
|
||||
def __init__(self, scl, sda, frequency=400000):
|
||||
self.init(scl, sda, frequency)
|
||||
|
|
@ -22,14 +23,17 @@ class I2C(Lockable):
|
|||
self.deinit()
|
||||
if detector.board.ftdi_ft232h:
|
||||
from adafruit_blinka.microcontroller.ft232h.i2c import I2C
|
||||
|
||||
self._i2c = I2C(frequency=frequency)
|
||||
return
|
||||
elif detector.board.binho_nova:
|
||||
from adafruit_blinka.microcontroller.nova.i2c import I2C
|
||||
|
||||
self._i2c = I2C(frequency=frequency)
|
||||
return
|
||||
elif detector.board.microchip_mcp2221:
|
||||
from adafruit_blinka.microcontroller.mcp2221.i2c import I2C
|
||||
|
||||
self._i2c = I2C(frequency=frequency)
|
||||
return
|
||||
elif detector.board.any_embedded_linux:
|
||||
|
|
@ -37,6 +41,7 @@ class I2C(Lockable):
|
|||
else:
|
||||
from machine import I2C as _I2C
|
||||
from microcontroller.pin import i2cPorts
|
||||
|
||||
for portId, portScl, portSda in i2cPorts:
|
||||
try:
|
||||
if scl == portScl and sda == portSda:
|
||||
|
|
@ -46,7 +51,9 @@ class I2C(Lockable):
|
|||
pass
|
||||
else:
|
||||
raise ValueError(
|
||||
"No Hardware I2C on (scl,sda)={}\nValid I2C ports: {}".format((scl, sda), i2cPorts)
|
||||
"No Hardware I2C on (scl,sda)={}\nValid I2C ports: {}".format(
|
||||
(scl, sda), i2cPorts
|
||||
)
|
||||
)
|
||||
|
||||
self._lock = threading.RLock()
|
||||
|
|
@ -83,13 +90,34 @@ class I2C(Lockable):
|
|||
if end is None:
|
||||
return self._i2c.writeto(address, memoryview(buffer)[start:], stop=stop)
|
||||
else:
|
||||
return self._i2c.writeto(address, memoryview(buffer)[start:end], stop=stop)
|
||||
return self._i2c.writeto(
|
||||
address, memoryview(buffer)[start:end], stop=stop
|
||||
)
|
||||
return self._i2c.writeto(address, buffer, stop=stop)
|
||||
|
||||
def writeto_then_readfrom(self, address, buffer_out, buffer_in, *, out_start=0, out_end=None, in_start=0, in_end=None, stop=False):
|
||||
return self._i2c.writeto_then_readfrom(address, buffer_out, buffer_in,
|
||||
out_start=out_start, out_end=out_end,
|
||||
in_start=in_start, in_end=in_end, stop=stop)
|
||||
def writeto_then_readfrom(
|
||||
self,
|
||||
address,
|
||||
buffer_out,
|
||||
buffer_in,
|
||||
*,
|
||||
out_start=0,
|
||||
out_end=None,
|
||||
in_start=0,
|
||||
in_end=None,
|
||||
stop=False
|
||||
):
|
||||
return self._i2c.writeto_then_readfrom(
|
||||
address,
|
||||
buffer_out,
|
||||
buffer_in,
|
||||
out_start=out_start,
|
||||
out_end=out_end,
|
||||
in_start=in_start,
|
||||
in_end=in_end,
|
||||
stop=stop,
|
||||
)
|
||||
|
||||
|
||||
class SPI(Lockable):
|
||||
def __init__(self, clock, MOSI=None, MISO=None):
|
||||
|
|
@ -97,12 +125,14 @@ class SPI(Lockable):
|
|||
if detector.board.ftdi_ft232h:
|
||||
from adafruit_blinka.microcontroller.ft232h.spi import SPI as _SPI
|
||||
from adafruit_blinka.microcontroller.ft232h.pin import SCK, MOSI, MISO
|
||||
|
||||
self._spi = _SPI()
|
||||
self._pins = (SCK, MOSI, MISO)
|
||||
return
|
||||
elif detector.board.binho_nova:
|
||||
from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
|
||||
from adafruit_blinka.microcontroller.nova.pin import SCK, MOSI, MISO
|
||||
|
||||
self._spi = _SPI(clock)
|
||||
self._pins = (SCK, MOSI, MISO)
|
||||
return
|
||||
|
|
@ -111,17 +141,22 @@ class SPI(Lockable):
|
|||
else:
|
||||
from machine import SPI as _SPI
|
||||
from microcontroller.pin import spiPorts
|
||||
|
||||
for portId, portSck, portMosi, portMiso in spiPorts:
|
||||
if ((clock == portSck) and # Clock is required!
|
||||
(MOSI == portMosi or MOSI == None) and # But can do with just output
|
||||
(MISO == portMiso or MISO == None)): # Or just input
|
||||
if (
|
||||
(clock == portSck)
|
||||
and (MOSI == portMosi or MOSI == None) # Clock is required!
|
||||
and (MISO == portMiso or MISO == None) # But can do with just output
|
||||
): # Or just input
|
||||
self._spi = _SPI(portId)
|
||||
self._pins = (portSck, portMosi, portMiso)
|
||||
break
|
||||
else:
|
||||
raise ValueError(
|
||||
"No Hardware SPI on (SCLK, MOSI, MISO)={}\nValid SPI ports:{}".
|
||||
format((clock, MOSI, MISO), spiPorts))
|
||||
"No Hardware SPI on (SCLK, MOSI, MISO)={}\nValid SPI ports:{}".format(
|
||||
(clock, MOSI, MISO), spiPorts
|
||||
)
|
||||
)
|
||||
|
||||
def configure(self, baudrate=100000, polarity=0, phase=0, bits=8):
|
||||
if detector.board.any_raspberry_pi or detector.board.any_raspberry_pi_40_pin:
|
||||
|
|
@ -172,7 +207,11 @@ class SPI(Lockable):
|
|||
elif detector.board.binho_nova:
|
||||
from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
|
||||
from adafruit_blinka.microcontroller.nova.pin import Pin
|
||||
elif board_id == ap_board.PINE64 or board_id == ap_board.PINEBOOK or board_id == ap_board.PINEPHONE:
|
||||
elif (
|
||||
board_id == ap_board.PINE64
|
||||
or board_id == ap_board.PINEBOOK
|
||||
or board_id == ap_board.PINEPHONE
|
||||
):
|
||||
from adafruit_blinka.microcontroller.allwinner.a64.pin import Pin
|
||||
from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
|
||||
elif board_id == ap_board.CLOCKWORK_CPI3:
|
||||
|
|
@ -195,7 +234,7 @@ class SPI(Lockable):
|
|||
firstbit=_SPI.MSB,
|
||||
sck=Pin(self._pins[0].id),
|
||||
mosi=Pin(self._pins[1].id),
|
||||
miso=Pin(self._pins[2].id)
|
||||
miso=Pin(self._pins[2].id),
|
||||
)
|
||||
else:
|
||||
raise RuntimeError("First call try_lock()")
|
||||
|
|
@ -209,7 +248,9 @@ class SPI(Lockable):
|
|||
try:
|
||||
return self._spi.frequency
|
||||
except AttributeError:
|
||||
raise NotImplementedError("Frequency attribute not implemented for this platform")
|
||||
raise NotImplementedError(
|
||||
"Frequency attribute not implemented for this platform"
|
||||
)
|
||||
|
||||
def write(self, buf, start=0, end=None):
|
||||
return self._spi.write(buf, start, end)
|
||||
|
|
@ -217,8 +258,12 @@ class SPI(Lockable):
|
|||
def readinto(self, buf, start=0, end=None, write_value=0):
|
||||
return self._spi.readinto(buf, start, end, write_value=write_value)
|
||||
|
||||
def write_readinto(self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None):
|
||||
return self._spi.write_readinto(buffer_out, buffer_in, out_start, out_end, in_start, in_end)
|
||||
def write_readinto(
|
||||
self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
|
||||
):
|
||||
return self._spi.write_readinto(
|
||||
buffer_out, buffer_in, out_start, out_end, in_start, in_end
|
||||
)
|
||||
|
||||
|
||||
class UART(Lockable):
|
||||
|
|
@ -228,7 +273,8 @@ class UART(Lockable):
|
|||
Parity.ODD = Parity()
|
||||
Parity.EVEN = Parity()
|
||||
|
||||
def __init__(self,
|
||||
def __init__(
|
||||
self,
|
||||
tx,
|
||||
rx,
|
||||
baudrate=9600,
|
||||
|
|
@ -237,9 +283,12 @@ class UART(Lockable):
|
|||
stop=1,
|
||||
timeout=1000,
|
||||
receiver_buffer_size=64,
|
||||
flow=None):
|
||||
flow=None,
|
||||
):
|
||||
if detector.board.any_embedded_linux:
|
||||
raise RuntimeError('busio.UART not supported on this platform. Please use pyserial instead.')
|
||||
raise RuntimeError(
|
||||
"busio.UART not supported on this platform. Please use pyserial instead."
|
||||
)
|
||||
elif detector.board.binho_nova:
|
||||
from adafruit_blinka.microcontroller.nova.uart import UART as _UART
|
||||
else:
|
||||
|
|
@ -254,8 +303,8 @@ class UART(Lockable):
|
|||
|
||||
if flow is not None: # default 0
|
||||
raise NotImplementedError(
|
||||
"Parameter '{}' unsupported on {}".format(
|
||||
"flow", agnostic.board_id))
|
||||
"Parameter '{}' unsupported on {}".format("flow", agnostic.board_id)
|
||||
)
|
||||
|
||||
# translate parity flag for Micropython
|
||||
if parity is UART.Parity.ODD:
|
||||
|
|
@ -277,12 +326,14 @@ class UART(Lockable):
|
|||
parity=parity,
|
||||
stop=stop,
|
||||
timeout=timeout,
|
||||
read_buf_len=receiver_buffer_size
|
||||
read_buf_len=receiver_buffer_size,
|
||||
)
|
||||
break
|
||||
else:
|
||||
raise ValueError(
|
||||
"No Hardware UART on (tx,rx)={}\nValid UART ports: {}".format((tx, rx), uartPorts)
|
||||
"No Hardware UART on (tx,rx)={}\nValid UART ports: {}".format(
|
||||
(tx, rx), uartPorts
|
||||
)
|
||||
)
|
||||
|
||||
def deinit(self):
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ elif detector.board.microchip_mcp2221:
|
|||
from adafruit_blinka.microcontroller.mcp2221.pin import Pin
|
||||
from adafruit_blinka import Enum, ContextManaged
|
||||
|
||||
|
||||
class DriveMode(Enum):
|
||||
PUSH_PULL = None
|
||||
OPEN_DRAIN = None
|
||||
|
|
@ -147,8 +148,9 @@ class DigitalInOut(ContextManaged):
|
|||
if hasattr(Pin, "PULL_DOWN"):
|
||||
self._pin.init(mode=Pin.IN, pull=Pin.PULL_DOWN)
|
||||
else:
|
||||
raise NotImplementedError("{} unsupported on {}".format(
|
||||
Pull.DOWN, board_id))
|
||||
raise NotImplementedError(
|
||||
"{} unsupported on {}".format(Pull.DOWN, board_id)
|
||||
)
|
||||
elif pul is None:
|
||||
self._pin.init(mode=Pin.IN, pull=None)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -4,23 +4,31 @@ from adafruit_platformdetect.constants import chips as ap_chip
|
|||
from adafruit_blinka import Enum
|
||||
from adafruit_blinka.agnostic import board_id, chip_id
|
||||
|
||||
|
||||
class Pin(Enum):
|
||||
"""Reference Pin object"""
|
||||
|
||||
def __init__(self, pin_id):
|
||||
"""Identifier for pin, referencing platform-specific pin id"""
|
||||
self._id = pin_id
|
||||
|
||||
def __repr__(self):
|
||||
# pylint: disable=import-outside-toplevel
|
||||
import board
|
||||
|
||||
for key in dir(board):
|
||||
if getattr(board, key) is self:
|
||||
return "board.{}".format(key)
|
||||
import microcontroller.pin as pin
|
||||
|
||||
# pylint: enable=import-outside-toplevel
|
||||
|
||||
for key in dir(pin):
|
||||
if getattr(pin, key) is self:
|
||||
return "microcontroller.pin.{}".format(key)
|
||||
return repr(self)
|
||||
|
||||
|
||||
# We intentionally are patching into this namespace so skip the wildcard check.
|
||||
# pylint: disable=unused-wildcard-import,wildcard-import,ungrouped-imports
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,16 @@
|
|||
# mitigate heap fragmentation issues by pre-loading major libraries
|
||||
import gc
|
||||
|
||||
gc.collect()
|
||||
import unittest
|
||||
|
||||
gc.collect()
|
||||
|
||||
|
||||
def yes_no(q, default=True):
|
||||
a = input(q + " (Y/n)?" if default else " (y/N)?")
|
||||
a = a.lower()
|
||||
if a == '':
|
||||
if a == "":
|
||||
return default
|
||||
elif a == "n":
|
||||
a = False
|
||||
|
|
@ -15,6 +18,7 @@ def yes_no(q, default=True):
|
|||
a = True
|
||||
return a
|
||||
|
||||
|
||||
def multi_choice(q, choices, defaultPos=None):
|
||||
if defaultPos is not None:
|
||||
print("{} [{}]?".format(q, defaultPos))
|
||||
|
|
@ -25,7 +29,7 @@ def multi_choice(q, choices, defaultPos=None):
|
|||
a = input()
|
||||
a = a.lower()
|
||||
try:
|
||||
if a == '':
|
||||
if a == "":
|
||||
a = defaultPos
|
||||
else:
|
||||
a = int(a)
|
||||
|
|
@ -34,8 +38,10 @@ def multi_choice(q, choices, defaultPos=None):
|
|||
print(e)
|
||||
return None
|
||||
|
||||
|
||||
def await_true(name, fun, interval=0, patience=60):
|
||||
from adafruit_blinka.agnostic.time import sleep, monotonic
|
||||
|
||||
print("Waiting {} sec until {} (CTRL+C give up)".format(patience, name))
|
||||
|
||||
deadline = monotonic() + patience
|
||||
|
|
@ -52,6 +58,7 @@ def await_true(name, fun, interval=0, patience=60):
|
|||
|
||||
def test_module(module, runner=None):
|
||||
import unittest
|
||||
|
||||
if runner is None:
|
||||
runner = unittest.TestRunner()
|
||||
suite = unittest.TestSuite()
|
||||
|
|
@ -64,6 +71,7 @@ def test_module(module, runner=None):
|
|||
pass
|
||||
return runner.run(suite)
|
||||
|
||||
|
||||
def test_module_name(absolute, runner=None):
|
||||
try:
|
||||
print("Suite begin: {}".format(absolute))
|
||||
|
|
@ -76,6 +84,7 @@ def test_module_name(absolute, runner=None):
|
|||
finally:
|
||||
print("Suite end: {}".format(absolute))
|
||||
|
||||
|
||||
def test_interactive(*module_names):
|
||||
for module_name in module_names:
|
||||
if yes_no("Run suite {}".format(module_name)):
|
||||
|
|
@ -97,8 +106,13 @@ def main():
|
|||
"""
|
||||
moduleNames = ["testing.implementation.universal.bitbangio"]
|
||||
|
||||
unittest.raiseException = True # terminates with stack information on userspace Exception
|
||||
unittest.raiseBaseException = True # terminates with stack information on system Exception
|
||||
unittest.raiseException = (
|
||||
True # terminates with stack information on userspace Exception
|
||||
)
|
||||
unittest.raiseBaseException = (
|
||||
True # terminates with stack information on system Exception
|
||||
)
|
||||
test_interactive(*moduleNames)
|
||||
|
||||
|
||||
gc.collect()
|
||||
|
|
@ -10,8 +10,10 @@ class TestEnum(unittest.TestCase):
|
|||
def setUp(self):
|
||||
"""Create an example Enum, mocking __module__ and __qualname__"""
|
||||
import adafruit_blinka
|
||||
|
||||
class Cls(adafruit_blinka.Enum):
|
||||
pass
|
||||
|
||||
Cls.one = Cls()
|
||||
Cls.two = Cls()
|
||||
# class refs would be implicitly populated correctly in a real module
|
||||
|
|
@ -19,13 +21,11 @@ class TestEnum(unittest.TestCase):
|
|||
Cls.__qualname__ = "Example"
|
||||
self.Cls = Cls
|
||||
|
||||
|
||||
def test_iteritems(self):
|
||||
"""A subtype of Enum can list all attributes of its own type"""
|
||||
items = list(self.Cls.iteritems())
|
||||
self.assertEqual(items, [("one", self.Cls.one), ("two", self.Cls.two),])
|
||||
|
||||
|
||||
def test_repr(self):
|
||||
"""A repr() call on an Enum gives its fully-qualified name"""
|
||||
name = "one"
|
||||
|
|
@ -33,17 +33,16 @@ class TestEnum(unittest.TestCase):
|
|||
expected = "{}.{}.{}".format(self.Cls.__module__, self.Cls.__qualname__, name)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
|
||||
def test_str(self):
|
||||
"""A str() call on an Enum performs the same as repr()"""
|
||||
self.assertEqual(str(self.Cls.one), repr(self.Cls.one))
|
||||
|
||||
|
||||
class TestDigitalInOut(unittest.TestCase):
|
||||
|
||||
|
||||
def test_context_manager(self):
|
||||
import digitalio
|
||||
from testing.board import default_pin
|
||||
|
||||
"""Deinitialisation is triggered by __exit__() and should dispose machine.pin reference"""
|
||||
dio = digitalio.DigitalInOut(default_pin)
|
||||
self.assertIsNotNone(dio._pin)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
from adafruit_blinka import agnostic
|
||||
|
||||
if agnostic.board in ("feather_m0_express", "feather_huzzah"):
|
||||
from bitbangio import I2C
|
||||
elif agnostic.board == "pyboard":
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ from testing import yes_no, await_true
|
|||
from testing.board import led_pin, default_pin, led_hardwired, led_inverted
|
||||
from digitalio import *
|
||||
|
||||
class TestDigitalInOut(unittest.TestCase):
|
||||
|
||||
class TestDigitalInOut(unittest.TestCase):
|
||||
def test_default(self):
|
||||
"""DigitalInOut is input with no pull when constructed"""
|
||||
with DigitalInOut(default_pin) as dio:
|
||||
|
|
@ -29,11 +29,11 @@ class TestDigitalInOut(unittest.TestCase):
|
|||
|
||||
|
||||
class TestDigitalInOutInteractive(unittest.TestCase):
|
||||
|
||||
def test_blink(self):
|
||||
"""LED blinks when proper attributes set"""
|
||||
print()
|
||||
from adafruit_blinka.agnostic import sleep
|
||||
|
||||
if not (led_hardwired) and not (yes_no("Is LED wired to {}".format(led_pin))):
|
||||
return # test trivially passed
|
||||
with DigitalInOut(led_pin) as led:
|
||||
|
|
@ -64,7 +64,9 @@ class TestDigitalInOutInteractive(unittest.TestCase):
|
|||
return # pull unsupported, test trivially passed
|
||||
if yes_no("Is Button wired from {} to GND".format(default_pin)):
|
||||
self.assertTrue(button.value == True)
|
||||
self.assertTrue(await_true("button pressed", lambda: button.value == False))
|
||||
self.assertTrue(
|
||||
await_true("button pressed", lambda: button.value == False)
|
||||
)
|
||||
|
||||
def test_button_pull_down(self):
|
||||
print()
|
||||
|
|
@ -79,7 +81,8 @@ class TestDigitalInOutInteractive(unittest.TestCase):
|
|||
except Exception as e:
|
||||
print(e)
|
||||
return # pull unsupported, test trivially passed
|
||||
if (yes_no("Is Button wired from {} to VCC".format(default_pin))):
|
||||
if yes_no("Is Button wired from {} to VCC".format(default_pin)):
|
||||
self.assertTrue(button.value == False)
|
||||
self.assertTrue(await_true("button pressed", lambda: button.value == True))
|
||||
|
||||
self.assertTrue(
|
||||
await_true("button pressed", lambda: button.value == True)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,21 +1,28 @@
|
|||
import gc
|
||||
from testing import yes_no
|
||||
|
||||
gc.collect()
|
||||
from unittest import TestCase
|
||||
|
||||
gc.collect()
|
||||
from testing.board.i2c import I2C
|
||||
|
||||
gc.collect()
|
||||
|
||||
class TestBME280Interactive(TestCase):
|
||||
|
||||
class TestBME280Interactive(TestCase):
|
||||
def test_read_value(self):
|
||||
|
||||
import board
|
||||
|
||||
gc.collect()
|
||||
import adafruit_bme280
|
||||
|
||||
gc.collect()
|
||||
|
||||
if not(yes_no("Is BME280 wired to SCL {} SDA {}".format(board.SCL, board.SDA))):
|
||||
if not (
|
||||
yes_no("Is BME280 wired to SCL {} SDA {}".format(board.SCL, board.SDA))
|
||||
):
|
||||
return # test trivially passed
|
||||
|
||||
i2c = I2C(board.SCL, board.SDA)
|
||||
|
|
@ -36,17 +43,25 @@ class TestBME280Interactive(TestCase):
|
|||
|
||||
|
||||
class TestMMA8451Interactive(TestCase):
|
||||
|
||||
def test_read_value(self):
|
||||
import math
|
||||
|
||||
gc.collect()
|
||||
import board
|
||||
|
||||
gc.collect()
|
||||
|
||||
if not(yes_no("Is MMA8451 wired to SCL {} SDA {} and held still".format(board.SCL, board.SDA))):
|
||||
if not (
|
||||
yes_no(
|
||||
"Is MMA8451 wired to SCL {} SDA {} and held still".format(
|
||||
board.SCL, board.SDA
|
||||
)
|
||||
)
|
||||
):
|
||||
return # test trivially passed
|
||||
# from https://github.com/adafruit/Adafruit_CircuitPython_MMA8451/blob/29e31a0bb836367bc73763b83513105252b7b264/examples/simpletest.py
|
||||
import adafruit_mma8451
|
||||
|
||||
i2c = I2C(board.SCL, board.SDA)
|
||||
sensor = adafruit_mma8451.MMA8451(i2c)
|
||||
|
||||
|
|
@ -55,7 +70,9 @@ class TestMMA8451Interactive(TestCase):
|
|||
self.assertTrue(9 <= absolute <= 11, "Not earth gravity")
|
||||
|
||||
orientation = sensor.orientation
|
||||
self.assertTrue(orientation in (
|
||||
self.assertTrue(
|
||||
orientation
|
||||
in (
|
||||
adafruit_mma8451.PL_PUF,
|
||||
adafruit_mma8451.PL_PUB,
|
||||
adafruit_mma8451.PL_PDF,
|
||||
|
|
@ -64,10 +81,11 @@ class TestMMA8451Interactive(TestCase):
|
|||
adafruit_mma8451.PL_LRB,
|
||||
adafruit_mma8451.PL_LLF,
|
||||
adafruit_mma8451.PL_LLB,
|
||||
))
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class TestBNO055Interactive(TestCase):
|
||||
|
||||
def test_read_value(self):
|
||||
"""
|
||||
Access all sensor values as per
|
||||
|
|
@ -76,8 +94,10 @@ class TestBNO055Interactive(TestCase):
|
|||
See https://forums.adafruit.com/viewtopic.php?f=60&t=131665
|
||||
"""
|
||||
import board
|
||||
|
||||
gc.collect()
|
||||
import adafruit_bno055
|
||||
|
||||
gc.collect()
|
||||
i2c = I2C(board.SCL, board.SDA)
|
||||
sensor = adafruit_bno055.BNO055(i2c)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
import unittest
|
||||
|
||||
class TestMicrocontrollerModule(unittest.TestCase):
|
||||
|
||||
class TestMicrocontrollerModule(unittest.TestCase):
|
||||
def test_pins_exist(self):
|
||||
"""The microcontroller module should contain pin references"""
|
||||
import microcontroller
|
||||
from microcontroller import pin
|
||||
from testing.microcontroller import pin_count
|
||||
|
||||
entries = [getattr(pin, key) for key in dir(pin)]
|
||||
# is this filter line needed? any other types valid in pin module?
|
||||
entries = list(filter(lambda val: type(val) is microcontroller.Pin, entries))
|
||||
|
|
|
|||
|
|
@ -1,20 +1,24 @@
|
|||
import gc
|
||||
from unittest import TestCase
|
||||
from testing import await_true
|
||||
|
||||
gc.collect()
|
||||
|
||||
|
||||
class TestGPSInteractive(TestCase):
|
||||
|
||||
def test_read_value(self):
|
||||
import adafruit_blinka
|
||||
|
||||
adafruit_blinka.patch_system() # needed before adafruit_gps imports time
|
||||
|
||||
import microcontroller.pin
|
||||
|
||||
gc.collect()
|
||||
import busio
|
||||
|
||||
gc.collect()
|
||||
import adafruit_gps
|
||||
|
||||
gc.collect()
|
||||
|
||||
# configure the last available UART (first uart often for REPL)
|
||||
|
|
@ -23,8 +27,8 @@ class TestGPSInteractive(TestCase):
|
|||
|
||||
gps = adafruit_gps.GPS(uart)
|
||||
|
||||
gps.send_command('PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
|
||||
gps.send_command('PMTK220,1000')
|
||||
gps.send_command("PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0")
|
||||
gps.send_command("PMTK220,1000")
|
||||
|
||||
def try_fix():
|
||||
gps.update()
|
||||
|
|
@ -35,4 +39,3 @@ class TestGPSInteractive(TestCase):
|
|||
self.assertTrue(gps.satellites is not None)
|
||||
self.assertTrue(-90 <= gps.latitude < 90)
|
||||
self.assertTrue(-180 <= gps.longitude < 180)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,16 @@
|
|||
"""Based on https://raw.githubusercontent.com/micropython/micropython-lib/cfa1b9cce0c93a3115bbff3886c9bbcddd9e8047/unittest/unittest.py """
|
||||
import sys
|
||||
|
||||
|
||||
class SkipTest(Exception):
|
||||
pass
|
||||
|
||||
|
||||
raiseException = False
|
||||
raiseBaseException = True
|
||||
|
||||
class AssertRaisesContext:
|
||||
|
||||
class AssertRaisesContext:
|
||||
def __init__(self, exc):
|
||||
self.expected = exc
|
||||
|
||||
|
|
@ -23,21 +26,20 @@ class AssertRaisesContext:
|
|||
|
||||
|
||||
class TestCase:
|
||||
|
||||
def fail(self, msg=''):
|
||||
def fail(self, msg=""):
|
||||
assert False, msg
|
||||
|
||||
def assertEqual(self, x, y, msg=''):
|
||||
def assertEqual(self, x, y, msg=""):
|
||||
if not msg:
|
||||
msg = "%r vs (expected) %r" % (x, y)
|
||||
assert x == y, msg
|
||||
|
||||
def assertNotEqual(self, x, y, msg=''):
|
||||
def assertNotEqual(self, x, y, msg=""):
|
||||
if not msg:
|
||||
msg = "%r not expected to be equal %r" % (x, y)
|
||||
assert x != y, msg
|
||||
|
||||
def assertAlmostEqual(self, x, y, places=None, msg='', delta=None):
|
||||
def assertAlmostEqual(self, x, y, places=None, msg="", delta=None):
|
||||
if x == y:
|
||||
return
|
||||
if delta is not None and places is not None:
|
||||
|
|
@ -47,18 +49,18 @@ class TestCase:
|
|||
if abs(x - y) <= delta:
|
||||
return
|
||||
if not msg:
|
||||
msg = '%r != %r within %r delta' % (x, y, delta)
|
||||
msg = "%r != %r within %r delta" % (x, y, delta)
|
||||
else:
|
||||
if places is None:
|
||||
places = 7
|
||||
if round(abs(y - x), places) == 0:
|
||||
return
|
||||
if not msg:
|
||||
msg = '%r != %r within %r places' % (x, y, places)
|
||||
msg = "%r != %r within %r places" % (x, y, places)
|
||||
|
||||
assert False, msg
|
||||
|
||||
def assertNotAlmostEqual(self, x, y, places=None, msg='', delta=None):
|
||||
def assertNotAlmostEqual(self, x, y, places=None, msg="", delta=None):
|
||||
if delta is not None and places is not None:
|
||||
raise TypeError("specify delta or places not both")
|
||||
|
||||
|
|
@ -66,53 +68,53 @@ class TestCase:
|
|||
if not (x == y) and abs(x - y) > delta:
|
||||
return
|
||||
if not msg:
|
||||
msg = '%r == %r within %r delta' % (x, y, delta)
|
||||
msg = "%r == %r within %r delta" % (x, y, delta)
|
||||
else:
|
||||
if places is None:
|
||||
places = 7
|
||||
if not (x == y) and round(abs(y - x), places) != 0:
|
||||
return
|
||||
if not msg:
|
||||
msg = '%r == %r within %r places' % (x, y, places)
|
||||
msg = "%r == %r within %r places" % (x, y, places)
|
||||
|
||||
assert False, msg
|
||||
|
||||
def assertIs(self, x, y, msg=''):
|
||||
def assertIs(self, x, y, msg=""):
|
||||
if not msg:
|
||||
msg = "%r is not %r" % (x, y)
|
||||
assert x is y, msg
|
||||
|
||||
def assertIsNot(self, x, y, msg=''):
|
||||
def assertIsNot(self, x, y, msg=""):
|
||||
if not msg:
|
||||
msg = "%r is %r" % (x, y)
|
||||
assert x is not y, msg
|
||||
|
||||
def assertIsNone(self, x, msg=''):
|
||||
def assertIsNone(self, x, msg=""):
|
||||
if not msg:
|
||||
msg = "%r is not None" % x
|
||||
assert x is None, msg
|
||||
|
||||
def assertIsNotNone(self, x, msg=''):
|
||||
def assertIsNotNone(self, x, msg=""):
|
||||
if not msg:
|
||||
msg = "%r is None" % x
|
||||
assert x is not None, msg
|
||||
|
||||
def assertTrue(self, x, msg=''):
|
||||
def assertTrue(self, x, msg=""):
|
||||
if not msg:
|
||||
msg = "Expected %r to be True" % x
|
||||
assert x, msg
|
||||
|
||||
def assertFalse(self, x, msg=''):
|
||||
def assertFalse(self, x, msg=""):
|
||||
if not msg:
|
||||
msg = "Expected %r to be False" % x
|
||||
assert not x, msg
|
||||
|
||||
def assertIn(self, x, y, msg=''):
|
||||
def assertIn(self, x, y, msg=""):
|
||||
if not msg:
|
||||
msg = "Expected %r to be in %r" % (x, y)
|
||||
assert x in y, msg
|
||||
|
||||
def assertIsInstance(self, x, y, msg=''):
|
||||
def assertIsInstance(self, x, y, msg=""):
|
||||
assert isinstance(x, y), msg
|
||||
|
||||
def assertRaises(self, exc, func=None, *args, **kwargs):
|
||||
|
|
@ -128,20 +130,23 @@ class TestCase:
|
|||
raise
|
||||
|
||||
|
||||
|
||||
def skip(msg):
|
||||
def _decor(fun):
|
||||
# We just replace original fun with _inner
|
||||
def _inner(self):
|
||||
raise SkipTest(msg)
|
||||
|
||||
return _inner
|
||||
|
||||
return _decor
|
||||
|
||||
|
||||
def skipIf(cond, msg):
|
||||
if not cond:
|
||||
return lambda x: x
|
||||
return skip(msg)
|
||||
|
||||
|
||||
def skipUnless(cond, msg):
|
||||
if cond:
|
||||
return lambda x: x
|
||||
|
|
@ -151,9 +156,11 @@ def skipUnless(cond, msg):
|
|||
class TestSuite:
|
||||
def __init__(self):
|
||||
self.tests = []
|
||||
|
||||
def addTest(self, cls):
|
||||
self.tests.append(cls)
|
||||
|
||||
|
||||
class TestRunner:
|
||||
def run(self, suite):
|
||||
res = TestResult()
|
||||
|
|
@ -171,6 +178,7 @@ class TestRunner:
|
|||
|
||||
return res
|
||||
|
||||
|
||||
class TestResult:
|
||||
def __init__(self):
|
||||
self.errorsNum = 0
|
||||
|
|
@ -181,6 +189,7 @@ class TestResult:
|
|||
def wasSuccessful(self):
|
||||
return self.errorsNum == 0 and self.failuresNum == 0
|
||||
|
||||
|
||||
# TODO: Uncompliant
|
||||
def run_class(c, test_result):
|
||||
o = c()
|
||||
|
|
@ -222,7 +231,11 @@ def main(module="__main__"):
|
|||
def test_cases(m):
|
||||
for tn in dir(m):
|
||||
c = getattr(m, tn)
|
||||
if isinstance(c, object) and isinstance(c, type) and issubclass(c, TestCase):
|
||||
if (
|
||||
isinstance(c, object)
|
||||
and isinstance(c, type)
|
||||
and issubclass(c, TestCase)
|
||||
):
|
||||
yield c
|
||||
|
||||
m = __import__(module) # changed to permit non-top-level testing modules
|
||||
|
|
|
|||
Loading…
Reference in a new issue