]> Repositories - Adafruit_Blinka-hackapet.git/commitdiff
Merge remote-tracking branch 'upstream/master'
authorFranklin Harding <franklin@harding.coffee>
Mon, 29 Mar 2021 01:00:48 +0000 (18:00 -0700)
committerFranklin Harding <franklin@harding.coffee>
Mon, 29 Mar 2021 01:00:48 +0000 (18:00 -0700)
96 files changed:
.github/workflows/build.yml
.pylintrc
README.rst
docs/api.rst
docs/conf.py
examples/analog_in.py [new file with mode: 0644]
examples/mcps_busio_i2c.py [new file with mode: 0755]
requirements.txt
setup.py
src/adafruit_blinka/__init__.py
src/adafruit_blinka/board/bananapi/__init__.py [new file with mode: 0644]
src/adafruit_blinka/board/bananapi/bpim2zero.py [new file with mode: 0644]
src/adafruit_blinka/board/beagleboard/beaglebone_ai.py [new file with mode: 0644]
src/adafruit_blinka/board/coral_dev_board.py [new file with mode: 0644]
src/adafruit_blinka/board/coral_dev_board_mini.py [new file with mode: 0644]
src/adafruit_blinka/board/coral_edge_tpu.py [deleted file]
src/adafruit_blinka/board/lubancat/__init__.py [new file with mode: 0644]
src/adafruit_blinka/board/lubancat/lubancat_imx6ull.py [new file with mode: 0644]
src/adafruit_blinka/board/nanopi/__init__.py [new file with mode: 0644]
src/adafruit_blinka/board/nanopi/duo2.py [new file with mode: 0644]
src/adafruit_blinka/board/nanopi/neoair.py [new file with mode: 0644]
src/adafruit_blinka/board/nvidia/clara_agx_xavier.py [new file with mode: 0644]
src/adafruit_blinka/board/nvidia/jetson_tx2_nx.py [new file with mode: 0644]
src/adafruit_blinka/board/orangepi/orangepizero2.py [new file with mode: 0644]
src/adafruit_blinka/board/orangepi/orangepizeroplus.py [new file with mode: 0644]
src/adafruit_blinka/board/orangepi/orangepizeroplus2h5.py [new file with mode: 0644]
src/adafruit_blinka/board/pineH64.py [new file with mode: 0644]
src/adafruit_blinka/board/pyboard.py
src/adafruit_blinka/board/radxa/rockpi4.py [new file with mode: 0644]
src/adafruit_blinka/board/radxa/rockpis.py
src/adafruit_blinka/board/soPine.py [new file with mode: 0644]
src/adafruit_blinka/board/stm32/__init__.py [new file with mode: 0644]
src/adafruit_blinka/board/stm32/stm32mp157c_dk2.py [new file with mode: 0644]
src/adafruit_blinka/board/udoo_x86ultra.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/allwinner/h3/pin.py
src/adafruit_blinka/microcontroller/allwinner/h5/__init__.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/allwinner/h5/pin.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/allwinner/h6/__init__.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/allwinner/h6/pin.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/allwinner/h616/__init__.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/allwinner/h616/pin.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/am335x/sysfs_pwmout.py
src/adafruit_blinka/microcontroller/amlogic/meson_g12_common/pin.py
src/adafruit_blinka/microcontroller/bcm283x/neopixel.py
src/adafruit_blinka/microcontroller/bcm283x/pin.py
src/adafruit_blinka/microcontroller/bcm283x/pulseio/PWMOut.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/bcm283x/pulseio/PulseIn.py
src/adafruit_blinka/microcontroller/dra74x/__init__.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/dra74x/pin.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/ftdi_mpsse/mpsse/pin.py
src/adafruit_blinka/microcontroller/ftdi_mpsse/mpsse/spi.py
src/adafruit_blinka/microcontroller/generic_linux/i2c.py
src/adafruit_blinka/microcontroller/generic_linux/libgpiod_pin.py
src/adafruit_blinka/microcontroller/generic_linux/periphery_pin.py
src/adafruit_blinka/microcontroller/generic_linux/sysfs_analogin.py
src/adafruit_blinka/microcontroller/generic_linux/sysfs_analogout.py
src/adafruit_blinka/microcontroller/generic_linux/sysfs_pin.py
src/adafruit_blinka/microcontroller/generic_linux/sysfs_pwmout.py
src/adafruit_blinka/microcontroller/mcp2221/i2c.py
src/adafruit_blinka/microcontroller/mcp2221/mcp2221.py
src/adafruit_blinka/microcontroller/mt8167/__init__.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/mt8167/pin.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/nova/__init__.py
src/adafruit_blinka/microcontroller/nova/i2c.py
src/adafruit_blinka/microcontroller/nova/pwmout.py
src/adafruit_blinka/microcontroller/nova/spi.py
src/adafruit_blinka/microcontroller/nova/uart.py
src/adafruit_blinka/microcontroller/nxp_imx6ull/__init__.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/nxp_imx6ull/pin.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/nxp_lpc4330/pin.py
src/adafruit_blinka/microcontroller/nxp_lpc4330/pwmout.py
src/adafruit_blinka/microcontroller/nxp_lpc4330/spi.py
src/adafruit_blinka/microcontroller/pentium/__init__.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/pentium/n3710/.gitignore [new file with mode: 0644]
src/adafruit_blinka/microcontroller/pentium/n3710/__init__.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/pentium/n3710/pin.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/rockchip/PWMOut.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/rockchip/rk3308/pin.py
src/adafruit_blinka/microcontroller/rockchip/rk3399/__init__.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/rockchip/rk3399/pin.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/stm32/stm32f405/__init__.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/stm32/stm32f405/pin.py [moved from src/adafruit_blinka/microcontroller/stm32/pin.py with 98% similarity]
src/adafruit_blinka/microcontroller/stm32/stm32mp157/__init__.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/stm32/stm32mp157/pin.py [new file with mode: 0755]
src/adafruit_blinka/microcontroller/tegra/t186/pin.py
src/adafruit_blinka/microcontroller/tegra/t194/pin.py
src/analogio.py
src/board.py
src/busio.py
src/digitalio.py
src/microcontroller/__init__.py
src/microcontroller/pin.py
src/neopixel_write.py
src/pulseio.py
src/pwmio.py [new file with mode: 0644]
test/src/testing/adafruit_blinka.py

index b0f79c273442b0faf46272c006a7839c073a3e79..f00cbfe4231e70a782eb36d472f4c7ac4d38e9b4 100644 (file)
@@ -35,7 +35,7 @@ jobs:
         source actions-ci/install.sh
     - name: Pip install pylint, black, & Sphinx
       run: |
-        pip install --force-reinstall pylint black==19.10b0 Sphinx sphinx-rtd-theme
+        pip install --force-reinstall pylint black Sphinx sphinx-rtd-theme
     - name: Library version
       run: git describe --dirty --always --tags
     - name: Check formatting
index 2c83b5ac3011d7281bb4b59950dba067fedd0266..35b40b5f25e2c8c0e29014566d2273daa3703d89 100644 (file)
--- a/.pylintrc
+++ b/.pylintrc
@@ -18,8 +18,8 @@ ignore-patterns=
 #init-hook=
 
 # Use multiple processes to speed up Pylint.
-jobs=1
-jobs=2
+jobs=1
+jobs=2
 
 # List of plugins (as comma separated values of python modules names) to load,
 # usually to register additional checkers.
@@ -249,7 +249,7 @@ ignore-docstrings=yes
 ignore-imports=no
 
 # Minimum lines number of a similarity.
-min-similarity-lines=4
+min-similarity-lines=80
 
 
 [BASIC]
index 5e806ad9efe439d258776cb5b409d0b7d21d1346..40df1a97b8ed2197ea54b64aa0a611136aa30b58 100755 (executable)
@@ -6,7 +6,7 @@ Introduction
     :alt: Documentation Status
 
 .. image:: https://img.shields.io/discord/327254708534116352.svg
-    :target: https://discord.gg/nBQh6qu
+    :target: https://adafru.it/discord
     :alt: Discord
 
 .. image:: https://travis-ci.com/adafruit/Adafruit_Blinka.svg?branch=master
@@ -26,8 +26,10 @@ on hosts running micropython. Working code exists to emulate the CircuitPython p
 * **digitalio** - digital input/output pins, using pin identities from board+microcontroller packages
 * **bitbangio** - software-driven interfaces for I2C, SPI
 * **busio** - hardware-driven interfaces for I2C, SPI, UART
-* **time** * - substitute functions monkey-patched to time module
+* **pulseio** - contains classes that provide access to basic pulse IO (PWM)
 
+For details, see the `Blinka API reference
+<https://circuitpython.readthedocs.io/projects/blinka/en/latest/index.html>`_.
 
 Dependencies
 =============
@@ -39,6 +41,31 @@ CircuitPython image, they have no value on a device already running CircuitPytho
 The test suites in the test/src folder under **testing.universal** are by design
 intended to run on *either* CircuitPython *or* Micropython+compatibility layer to prove conformance.
 
+Installing from PyPI
+=====================
+
+On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally `from
+PyPI <https://pypi.org/project/Adafruit-Blinka/>`_. To install for current user:
+
+.. code-block:: shell
+
+    pip3 install Adafruit-Blinka
+
+To install system-wide (this may be required in some cases):
+
+.. code-block:: shell
+
+    sudo pip3 install Adafruit-Blinka
+
+To install in a virtual environment in your current project:
+
+.. code-block:: shell
+
+    mkdir project-name && cd project-name
+    python3 -m venv .env
+    source .env/bin/activate
+    pip3 install Adafruit-Blinka
+
 Usage Example
 =============
 
@@ -52,7 +79,6 @@ the following sequence runs through some basic testing of the digitalio compatib
 
 An example log from running the suites is `here <https://github.com/cefn/Adafruit_Micropython_Blinka/issues/2#issuecomment-366713394>`_ .
 
-
 Contributing
 ============
 
@@ -73,7 +99,7 @@ install dependencies (feel free to reuse the virtual environment from above):
 
     python3 -m venv .env
     source .env/bin/activate
-    pip install Sphinx sphinx-rtd-theme
+    pip install Sphinx sphinx-rtd-theme Adafruit-PlatformDetect
 
 Now, once you have the virtual environment activated:
 
index 66bca16197c56cba3c0d2b6c4d56710261d609a8..61e9bbee5fc477d73425faa0a99dea71c333b0fb 100755 (executable)
 
 .. automodule:: digitalio
   :members:
+
+.. automodule:: analogio
+  :members:
+
+.. automodule:: pulseio
+  :members:
+
+.. automodule:: neopixel_write
+  :members:
+
+
index cadf23f9d371f9e9c96c30577e3f90d0f6f00eaa..7c11d8abdd1b7d8a0e7126448bfffe8995de46f7 100755 (executable)
@@ -19,10 +19,17 @@ extensions = [
 # Uncomment the below if you use native CircuitPython modules such as
 # digitalio, micropython and busio. List the modules you use. Without it, the
 # autodoc module docs will fail to generate with a warning.
-autodoc_mock_imports = ["machine", "Adafruit_GPIO"]
+autodoc_mock_imports = [
+    "machine",
+    "Adafruit_GPIO",
+    "RPi",
+    "RPi.GPIO",
+    "hid",
+    "sysv_ipc",
+]
 
 intersphinx_mapping = {
-    "python": ("https://docs.python.org/3.4", None),
+    "python": ("https://docs.python.org/3.6", None),
     "CircuitPython": ("https://circuitpython.readthedocs.io/en/latest/", None),
 }
 
diff --git a/examples/analog_in.py b/examples/analog_in.py
new file mode 100644 (file)
index 0000000..d72fbdc
--- /dev/null
@@ -0,0 +1,15 @@
+"""Analog in demo"""
+import time
+import board
+from analogio import AnalogIn
+
+analog_in = AnalogIn(board.A1)
+
+
+def get_voltage(pin):
+    return (pin.value * 3.3) / 4096
+
+
+while True:
+    print((get_voltage(analog_in),))
+    time.sleep(0.1)
diff --git a/examples/mcps_busio_i2c.py b/examples/mcps_busio_i2c.py
new file mode 100755 (executable)
index 0000000..4729e3e
--- /dev/null
@@ -0,0 +1,57 @@
+import time
+import hid
+import busio
+
+from adafruit_blinka.microcontroller.mcp2221.mcp2221 import mcp2221 as _mcp2221
+from adafruit_blinka.microcontroller.mcp2221.mcp2221 import MCP2221 as _MCP2221
+from adafruit_blinka.microcontroller.mcp2221.i2c import I2C as _MCP2221I2C
+
+MLXADDR = 0x33
+ADDRID1 = 0x2407
+
+
+class MCP2221(_MCP2221):  # pylint: disable=too-few-public-methods
+    def __init__(self, address):
+        self._hid = hid.device()
+        self._hid.open_path(address)
+        print("Connected to " + str(address))
+        self._gp_config = [0x07] * 4  # "don't care" initial value
+        for pin in range(4):
+            self.gp_set_mode(pin, self.GP_GPIO)  # set to GPIO mode
+            self.gpio_set_direction(pin, 1)  # set to INPUT
+
+
+class MCP2221I2C(_MCP2221I2C):  # pylint: disable=too-few-public-methods
+    def __init__(self, mcp2221, *, frequency=100000):
+        self._mcp2221 = mcp2221
+        self._mcp2221.i2c_configure(frequency)
+
+
+class I2C(busio.I2C):  # pylint: disable=too-few-public-methods
+    def __init__(self, mcp2221_i2c):
+        self._i2c = mcp2221_i2c
+
+
+addresses = [mcp["path"] for mcp in hid.enumerate(0x04D8, 0x00DD)]
+
+i2c_devices = []
+i2c_devices.append(I2C(MCP2221I2C(_mcp2221)))
+
+for addr in addresses:
+    try:
+        i2c_device = I2C(MCP2221I2C(MCP2221(addr)))
+        i2c_devices.append(i2c_device)
+    except OSError:
+        print("Device path: " + str(addr) + " is used")
+
+
+while True:
+    for i2c in i2c_devices:
+        addrbuf = bytearray(2)
+        addrbuf[0] = ADDRID1 >> 8
+        addrbuf[1] = ADDRID1 & 0xFF
+        inbuf = bytearray(6)
+        i2c.writeto_then_readfrom(MLXADDR, addrbuf, inbuf)
+        print("Device " + str(i2c_devices.index(i2c)) + ": ")
+        print(inbuf)
+        time.sleep(0.5)
index 21b3728f46d3e8b6aa7771c694f3c8b6525364ff..59a7ee916a585e7acd382963617089781428c1de 100755 (executable)
@@ -1,8 +1,8 @@
-Adafruit-PlatformDetect>=2.11.1
-Adafruit-PureIO>=1.1.5
+Adafruit-PlatformDetect>=3.1.0
+Adafruit-PureIO>=1.1.7
 Jetson.GPIO; platform_machine=='aarch64'
 RPi.GPIO; platform_machine=='armv7l' or platform_machine=='armv6l'
 rpi_ws281x>=4.0.0; platform_machine=='armv7l' or platform_machine=='armv6l'
-sysv_ipc; sys_platform == 'linux' and platform_machine!='mips'
+sysv_ipc>=1.1.0; sys_platform == 'linux' and platform_machine!='mips'
 pyftdi>=0.40.0
-binho-host-adapter>=0.1.4
+binho-host-adapter>=0.1.6
index c0c845026b498a949db45e5bd7a3bb04fa58c8ce..7e9259614c848eb555d1e71aa1e7549927b281bc 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -28,8 +28,9 @@ if os.path.exists("/proc/device-tree/compatible"):
         or b"brcm,bcm2836" in compat
         or b"brcm,bcm2837" in compat
         or b"brcm,bcm2838" in compat
+        or b"brcm,bcm2711" in compat
     ):
-        board_reqs = ["RPi.GPIO", "rpi_ws281x>=4.0.0"]
+        board_reqs = ["RPi.GPIO", "rpi_ws281x>=4.0.0", "sysv_ipc>=1.1.0"]
 
 setup(
     name="Adafruit-Blinka",
@@ -40,7 +41,7 @@ setup(
     long_description_content_type="text/x-rst",
     author="Adafruit Industries",
     author_email="circuitpython@adafruit.com",
-    python_requires=">=3.5.0",
+    python_requires=">=3.6.0",
     url="https://github.com/adafruit/Adafruit_Blinka",
     package_dir={"": "src"},
     packages=find_packages("src"),
@@ -54,15 +55,15 @@ setup(
         "digitalio",
         "micropython",
         "pulseio",
+        "pwmio",
         "neopixel_write",
     ],
     package_data={
         "adafruit_blinka.microcontroller.bcm283x.pulseio": ["libgpiod_pulsein"]
     },
     install_requires=[
-        "Adafruit-PlatformDetect>=2.11.1",
-        "Adafruit-PureIO>=1.1.5",
-        "sysv_ipc; platform_system != 'Windows' and platform_machine != 'mips'",
+        "Adafruit-PlatformDetect>=3.1.0",
+        "Adafruit-PureIO>=1.1.7",
         "pyftdi>=0.40.0",
     ]
     + board_reqs,
@@ -73,7 +74,7 @@ setup(
         "License :: OSI Approved :: MIT License",
         "Programming Language :: Python",
         "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.5",
+        "Programming Language :: Python :: 3.6",
         "Programming Language :: Python :: Implementation :: MicroPython",
     ],
 )
index 2df8a2d702228cd493a493da985788753c47081c..69e917851be562cef45acbaa934d58b1518be6b5 100755 (executable)
@@ -8,8 +8,8 @@
 
 class Enum:
     """
-        Object supporting CircuitPython-style of static symbols
-        as seen with Direction.OUTPUT, Pull.UP
+    Object supporting CircuitPython-style of static symbols
+    as seen with Direction.OUTPUT, Pull.UP
     """
 
     def __repr__(self):
@@ -27,8 +27,8 @@ class Enum:
     @classmethod
     def iteritems(cls):
         """
-            Inspects attributes of the class for instances of the class
-            and returns as key,value pairs mirroring dict#iteritems
+        Inspects attributes of the class for instances of the class
+        and returns as key,value pairs mirroring dict#iteritems
         """
         for key in dir(cls):
             val = getattr(cls, key)
diff --git a/src/adafruit_blinka/board/bananapi/__init__.py b/src/adafruit_blinka/board/bananapi/__init__.py
new file mode 100644 (file)
index 0000000..8d40623
--- /dev/null
@@ -0,0 +1 @@
+"""Boards definition from Banana Pi"""
diff --git a/src/adafruit_blinka/board/bananapi/bpim2zero.py b/src/adafruit_blinka/board/bananapi/bpim2zero.py
new file mode 100644 (file)
index 0000000..10da54b
--- /dev/null
@@ -0,0 +1,79 @@
+"""Pin definitions for the Banana Pi M2 Zero."""
+
+# The Banana Pi M2 Zero uses the AllWinner H2 SoC, but pins
+# are the same as the AllWinner H3 SoC, so we import those
+from adafruit_blinka.microcontroller.allwinner.h3 import pin
+
+PA12 = pin.PA12
+SDA = pin.PA12
+PA11 = pin.PA11
+SCL = pin.PA11
+PA6 = pin.PA6
+PWM1 = pin.PA6
+PA1 = pin.PA1
+UART2_RX = pin.PA1
+PA0 = pin.PA0
+UART2_TX = pin.PA0
+PA3 = pin.PA3
+UART2_CTS = pin.PA3
+PA10 = pin.PA10
+PA12 = pin.PA12
+SDA = pin.PA12
+PA11 = pin.PA11
+SCL = pin.PA11
+PA6 = pin.PA6
+PWM1 = pin.PA6
+PA1 = pin.PA1
+UART2_RX = pin.PA1
+PA0 = pin.PA0
+UART2_TX = pin.PA0
+PA3 = pin.PA3
+UART2_CTS = pin.PA3
+PA7 = pin.PA7
+PA8 = pin.PA8
+PA9 = pin.PA9
+PA10 = pin.PA10
+PA17 = pin.PA17
+PA18 = pin.PA18
+PA19 = pin.PA19
+PA20 = pin.PA20
+PA21 = pin.PA21
+PC0 = pin.PC0
+PC1 = pin.PC1
+PC2 = pin.PC2
+PC3 = pin.PC3
+PC4 = pin.PC4
+PC7 = pin.PC7
+
+PA13 = pin.PA13
+SPI1_CS = pin.PA13
+PA14 = pin.PA14
+SPI1_CLK = pin.PA14
+PA2 = pin.PA2
+UART2_RTS = pin.PA2
+PA18 = pin.PA18
+TWI1_SCK = pin.PA18
+
+PL2 = pin.PL2
+PL4 = pin.PL4
+
+SCLK = pin.PA14
+MOSI = pin.PA15
+MISO = pin.PA16
+
+PA13 = pin.PA13
+SPI1_CS = pin.PA13
+PA14 = pin.PA14
+SPI1_CLK = pin.PA14
+PA2 = pin.PA2
+UART2_RTS = pin.PA2
+PA18 = pin.PA18
+TWI1_SCK = pin.PA18
+PG6 = pin.PG6
+UART1_TX = pin.PG6
+PG7 = pin.PG7
+UART1_RX = pin.PG7
+
+SCLK = pin.PA14
+MOSI = pin.PA15
+MISO = pin.PA16
diff --git a/src/adafruit_blinka/board/beagleboard/beaglebone_ai.py b/src/adafruit_blinka/board/beagleboard/beaglebone_ai.py
new file mode 100644 (file)
index 0000000..d88111f
--- /dev/null
@@ -0,0 +1,140 @@
+"""Pin definitions for the Beaglebone Black."""
+from adafruit_blinka.microcontroller.dra74x import pin
+
+# initial pins, to mimic bonescript demo
+# BeagleBone Black
+# P8_1 = DGND        # DGND
+# P8_2 = DGND        # DGND
+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
+# P9_2 = DGND        # DGND
+# P9_3 = VDD_3V3     # VDD_3V3
+# P9_4 = VDD_3V3     # VDD_3V3
+# P9_5 = VDD_5V      # VDD_5V
+# P9_6 = VDD_5V      # VDD_5V
+# P9_7 = SYS_5V      # SYS_5V
+# P9_8 = SYS_5V      # SYS_5V
+# P9_9 = PWR_BUT     # PWR_BUT
+# P9_10 = SYS_RESETN # SYS_RESETn
+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
+# P9_33 = AIN4       # AIN4
+# P9_34 = GNDA_ADC   # GNDA_ADC
+# P9_35 = AIN6       # AIN6
+# P9_36 = AIN5       # AIN5
+# P9_37 = AIN2       # AIN2
+# P9_38 = AIN3       # AIN3
+# P9_39 = AIN0       # AIN0
+# P9_40 = AIN1       # AIN1
+P9_41 = pin.P9_41  # CLKOUT2 - GPIO_20
+P9_42 = pin.P9_42  # GPIO0_7 - GPIO_7
+# P9_43 = DGND       # DGND
+# P9_44 = DGND       # DGND
+# P9_45 = DGND       # DGND
+# P9_46 = DGND       # DGND
+
+# common to all beagles
+LED_USR0 = pin.USR0
+LED_USR1 = pin.USR1
+LED_USR2 = pin.USR2
+LED_USR3 = pin.USR3
+LED_USR4 = pin.USR4
+
+# I2C and SPI pins from:
+# src/adafruit_blinka/board/raspi_40pin.py
+# SDA = pin.SDA
+# SCL = pin.SCL
+# CE1 = pin.D7
+# CE0 = pin.D8
+# MISO = pin.D9
+# MOSI = pin.D10
+# SCLK = pin.D11
+# SCK = pin.D11
+# TXD = pin.D14
+# RXD = pin.D15
+# MISO_1 = pin.D19
+# MOSI_1 = pin.D20
+# SCLK_1 = pin.D21
+# SCK_1 = pin.D21
+
+SDA = pin.I2C4_SDA  # P9_19
+SCL = pin.I2C4_SCL  # P9_20
+
+# Pins for SPI
+#
+# To enable SPI and an additional I2C port, add the following line to /boot/uEnv.txt:
+#    dtb=am5729-beagleboneai-roboticscape.dtb
+#
+# You can verify the dtb file exists by checking the /boot/dtbs/{kernel_version}/ folder
+#
+CE0 = pin.SPI1_CS0  # P9_28
+CE1 = pin.SPI1_CS1  # P9_42
+MOSI = pin.SPI1_D1  # P9_29
+MISO = pin.SPI1_D0  # P9_30
+SCLK = pin.SPI1_SCLK  # P9_31
+# CircuitPython naming convention for SPI Clock
+SCK = SCLK
diff --git a/src/adafruit_blinka/board/coral_dev_board.py b/src/adafruit_blinka/board/coral_dev_board.py
new file mode 100644 (file)
index 0000000..fd860d2
--- /dev/null
@@ -0,0 +1,24 @@
+"""Pin definitions for the Coral Dev Board."""
+
+from adafruit_blinka.microcontroller.nxp_imx8m import pin
+
+# Board name = RPI name [= alias] = pin name
+I2C2_SDA = D2 = SDA = pin.I2C2_SDA
+I2C2_SCL = D3 = SCL = pin.I2C2_SCL
+
+PWM1 = D12 = pin.PWM1
+PWM2 = D13 = pin.PWM2
+PWM3 = D22 = pin.PWM3
+
+GPIO_P13 = D27 = pin.GPIO6
+GPIO_P16 = D23 = pin.GPIO73
+GPIO_P18 = D24 = pin.GPIO138
+GPIO_P29 = D5 = pin.GPIO7
+GPIO_P31 = D6 = pin.GPIO8
+GPIO_P36 = D16 = pin.GPIO141
+GPIO_P37 = D26 = pin.GPIO77
+
+ECSPI1_MISO = D9 = MISO = pin.ECSPI1_MISO
+ECSPI1_MOSI = D10 = MOSI = pin.ECSPI1_MOSI
+ECSPI1_SCLK = D11 = SCLK = SCK = pin.ECSPI1_SCLK
+ECSPI1_SS0 = D8 = SS0 = pin.ECSPI1_SS0
diff --git a/src/adafruit_blinka/board/coral_dev_board_mini.py b/src/adafruit_blinka/board/coral_dev_board_mini.py
new file mode 100644 (file)
index 0000000..b0b425c
--- /dev/null
@@ -0,0 +1,38 @@
+"""Pin definitions for the Coral Dev Board Mini."""
+
+from adafruit_blinka.microcontroller.mt8167 import pin
+
+# Board name = RPI name [= alias] = pin name
+GPIO22 = D4 = pin.GPIO22  # Pin 7
+GPIO9 = D17 = pin.GPIO9  # Pin 11
+GPIO36 = D18 = pin.GPIO36  # Pin 12
+GPIO10 = D27 = pin.GPIO10  # Pin 13
+GPIO0 = D23 = pin.GPIO0  # Pin 16
+GPIO1 = D24 = pin.GPIO1  # Pin 18
+GPIO7 = D25 = pin.GPIO7  # Pin 22
+GPIO8 = D7 = pin.GPIO8  # Pin 26
+GPIO37 = D19 = pin.GPIO37  # Pin 35
+GPIO13 = D16 = pin.GPIO13  # Pin 36
+GPIO45 = D26 = pin.GPIO45  # Pin 37
+GPIO38 = D20 = pin.GPIO38  # Pin 38
+GPIO39 = D21 = pin.GPIO39  # Pin 40
+
+I2C1_SDA = D2 = SDA1 = pin.I2C1_SDA  # Pin 3
+I2C1_SCL = D3 = SCL1 = pin.I2C1_SCL  # Pin 5
+I2C2_SDA = D0 = SDA2 = pin.I2C2_SDA  # Pin 27
+I2C2_SCL = D1 = SCL2 = pin.I2C2_SCL  # Pin 28
+
+PWM_A = D12 = pin.PWM_A  # Pin 32
+PWM_B = D13 = pin.PWM_B  # Pin 33
+PWM_C = D22 = pin.PWM_C  # Pin 15
+
+SPI_MO = D10 = MOSI = pin.SPI_MO  # Pin 19
+SPI_MI = D9 = MISO = pin.SPI_MI  # Pin 21
+SPI_CLK = D11 = SCLK = pin.SPI_CLK  # Pin 23
+SPI_CSB = D8 = CS0 = pin.SPI_CSB  # Pin 24
+
+# UART currently not supported
+GPIO63 = D14 = pin.GPIO63  # UART0_TX, Pin 8
+GPIO62 = D15 = pin.GPIO62  # UART0_RX, Pin 10
+GPIO65 = D5 = pin.GPIO65  # UART1_TX, Pin 29
+GPIO64 = D6 = pin.GPIO64  # UART1_RX, Pin 31
diff --git a/src/adafruit_blinka/board/coral_edge_tpu.py b/src/adafruit_blinka/board/coral_edge_tpu.py
deleted file mode 100644 (file)
index 667e245..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-"""Pin definitions for the Coral Edge TPU Dev board."""
-
-from adafruit_blinka.microcontroller.nxp_imx8m import pin
-
-SDA = pin.I2C2_SDA
-SCL = pin.I2C2_SCL
-
-PWM1 = pin.PWM1
-PWM2 = pin.PWM2
-PWM3 = pin.PWM3
-
-GPIO_P13 = pin.GPIO6
-GPIO_P16 = pin.GPIO73
-GPIO_P18 = pin.GPIO138
-GPIO_P29 = pin.GPIO7
-GPIO_P31 = pin.GPIO8
-GPIO_P36 = pin.GPIO141
-GPIO_P37 = pin.GPIO77
-
-MISO = pin.ECSPI1_MISO
-MOSI = pin.ECSPI1_MOSI
-SCLK = pin.ECSPI1_SCLK
-SCK = pin.ECSPI1_SCLK
-SS0 = pin.ECSPI1_SS0
diff --git a/src/adafruit_blinka/board/lubancat/__init__.py b/src/adafruit_blinka/board/lubancat/__init__.py
new file mode 100644 (file)
index 0000000..d56e3ea
--- /dev/null
@@ -0,0 +1 @@
+"""Boards definition from LubanCat"""
diff --git a/src/adafruit_blinka/board/lubancat/lubancat_imx6ull.py b/src/adafruit_blinka/board/lubancat/lubancat_imx6ull.py
new file mode 100644 (file)
index 0000000..26a3221
--- /dev/null
@@ -0,0 +1,51 @@
+"""Pin definitions for the LubanCat IMX6ULL."""
+
+from adafruit_blinka.microcontroller.nxp_imx6ull import pin
+
+# Pro board pin header CN4 named GPIO_PAx, pin header CN5 named GPIO_PBx
+# Mini board pin header CN3 named GPIO_PCx, pin header CN4 named GPIO_PDx
+
+# Board pin name [= alias] = RPI name [= alias] = pin name
+GPIO_PC3 = I2C2_SDA = D2 = SDA = pin.I2C2_SDA
+GPIO_PC5 = I2C2_SCL = D3 = SCL = pin.I2C2_SCL
+
+GPIO_PC7 = D4 = pin.GPIO27
+GPIO_PC8 = D14 = TXD = pin.UART3_TXD
+GPIO_PC10 = D15 = RXD = pin.UART3_RXD
+GPIO_PC11 = ADC_IN3 = A3 = D17 = pin.GPIO3
+GPIO_PC12 = D18 = pin.GPIO112
+GPIO_PC13 = ADC_IN2 = A2 = D27 = pin.GPIO2
+GPIO_PC15 = ADC_IN0 = A0 = D22 = pin.GPIO0
+GPIO_PC16 = D23 = pin.GPIO119
+GPIO_PC18 = D24 = pin.GPIO114
+
+GPIO_PC19 = ECSPI3_MOSI = D10 = MOSI = pin.ECSPI3_MOSI
+GPIO_PC21 = ECSPI3_MISO = D9 = MISO = pin.ECSPI3_MISO
+GPIO_PC22 = D25 = pin.GPIO27
+GPIO_PC23 = ECSPI3_SCLK = D11 = SCLK = SCK = pin.ECSPI3_SCLK
+GPIO_PC24 = ECSPI3_SS0 = D8 = SS0 = pin.ECSPI3_SS0
+GPIO_PC26 = ECSPI3_SS1 = D7 = SS1 = pin.ECSPI3_SS1
+
+GPIO_PC27 = I2C3_SDA = D0 = pin.I2C3_SDA
+GPIO_PC28 = I2C3_SCL = D1 = pin.I2C3_SCL
+
+GPIO_PC29 = D5 = pin.GPIO117
+GPIO_PC31 = D6 = pin.GPIO118
+
+GPIO_PC32 = LED_D6 = D12 = pin.GPIO115
+GPIO_PC33 = LED_D5 = D13 = pin.GPIO116
+
+# Board pwm channel = RPI PWM Channel = pin name
+PWM_C7 = PWM1 = pin.GPIO115
+PWM_C8 = PWM2 = pin.GPIO116
+
+GPIO_PC35 = D19 = pin.GPIO121
+GPIO_PC36 = D16 = pin.GPIO120
+GPIO_PC37 = D26 = pin.GPIO26
+GPIO_PC38 = D20 = pin.GPIO123
+GPIO_PC40 = D21 = pin.GPIO124
+
+# Mini header CN4
+GPIO_PD9 = ADC_IN1 = A1 = pin.GPIO1
+GPIO_PD4 = LED_D4 = PWM_C3 = pin.GPIO4
+GPIO_PD17 = BUTTON2 = pin.GPIO129
diff --git a/src/adafruit_blinka/board/nanopi/__init__.py b/src/adafruit_blinka/board/nanopi/__init__.py
new file mode 100644 (file)
index 0000000..64e3b6c
--- /dev/null
@@ -0,0 +1 @@
+"""Board definitions from NanoPi"""
diff --git a/src/adafruit_blinka/board/nanopi/duo2.py b/src/adafruit_blinka/board/nanopi/duo2.py
new file mode 100644 (file)
index 0000000..368c939
--- /dev/null
@@ -0,0 +1,23 @@
+"""Pin definitions for the NanoPi Duo2."""
+# Enable I2C0, UART1, and SPI by adding the following lines to /boot/armbianEnv.txt
+#    overlays=usbhost2 usbhost3 spi-spidev uart1 i2c0
+#    param_spidev_spi_bus=0
+
+from adafruit_blinka.microcontroller.allwinner.h3 import pin
+
+# Left GPIO
+PG11 = pin.PG11
+
+# I2C
+SDA = pin.PA12
+SCL = pin.PA11
+
+# SPI
+SCLK = pin.PA14
+MOSI = pin.PA15
+MISO = pin.PA16
+CE0 = pin.PA13
+
+# Serial UART
+UART1_TX = pin.PG6
+UART1_RX = pin.PG7
diff --git a/src/adafruit_blinka/board/nanopi/neoair.py b/src/adafruit_blinka/board/nanopi/neoair.py
new file mode 100644 (file)
index 0000000..68b5cbe
--- /dev/null
@@ -0,0 +1,49 @@
+"""Pin definitions for the NanoPi NEO Air."""
+# Enable I2C0, UART1, and SPI by adding the following lines to /boot/armbianEnv.txt
+#    overlays=usbhost2 usbhost3 spi-spidev uart1 i2c0
+#    param_spidev_spi_bus=0
+
+from adafruit_blinka.microcontroller.allwinner.h3 import pin
+
+# Left GPIOs
+D2 = pin.PA12
+D3 = pin.PA11
+D4 = pin.PG11
+D17 = pin.PA0
+D27 = pin.PA2
+D22 = pin.PA3
+D10 = pin.PC0
+D9 = pin.PC1
+D11 = pin.PC2
+
+# Right GPIOs
+D14 = pin.PG6
+D15 = pin.PG7
+D18 = pin.PA6
+D23 = pin.PG8
+D24 = pin.PG9
+D25 = pin.PA1
+D8 = pin.PC3
+
+# I2C
+SDA = D2
+SCL = D3
+
+# SPI
+SCLK = D11
+MOSI = D10
+MISO = D9
+CE0 = D8
+SCK = SCLK
+
+# Serial UART
+UART1_TX = D14
+UART1_RX = D15
+
+UART2_RX = D8
+UART2_TX = D17
+UART2_RTS = D27
+UART2_CTS = D22
+
+# PWM
+PWM1 = D4
diff --git a/src/adafruit_blinka/board/nvidia/clara_agx_xavier.py b/src/adafruit_blinka/board/nvidia/clara_agx_xavier.py
new file mode 100644 (file)
index 0000000..d65e95a
--- /dev/null
@@ -0,0 +1,38 @@
+"""Pin definitions for Clara AGX Xavier."""
+
+from adafruit_blinka.microcontroller.tegra.t194 import pin
+
+SDA = pin.SDA
+SCL = pin.SCL
+SDA_1 = pin.SDA_1
+SCL_1 = pin.SCL_1
+
+D4 = pin.Q06
+D5 = pin.AA03
+D6 = pin.AA02
+D7 = pin.Z07
+D8 = pin.Z06
+D9 = pin.Z04
+D10 = pin.Z05
+D11 = pin.Z03
+D12 = pin.BB01
+D13 = pin.AA00
+D16 = pin.R05
+D17 = pin.R04
+D18 = pin.H07
+D19 = pin.I02
+D20 = pin.I01
+D21 = pin.I00
+D22 = pin.N01
+D23 = pin.BB00
+D24 = pin.H00
+D25 = pin.Q01
+D26 = pin.AA01
+D27 = pin.P04
+
+CE1 = D7
+CE0 = D8
+MISO = D9
+MOSI = D10
+SCLK = D11
+SCK = D11
diff --git a/src/adafruit_blinka/board/nvidia/jetson_tx2_nx.py b/src/adafruit_blinka/board/nvidia/jetson_tx2_nx.py
new file mode 100644 (file)
index 0000000..ff5c154
--- /dev/null
@@ -0,0 +1,38 @@
+"""Pin definitions for Jetson TX2 NX."""
+
+from adafruit_blinka.microcontroller.tegra.t186 import pin
+
+SDA = pin.SDA
+SCL = pin.SCL
+SDA_1 = pin.SDA_1
+SCL_1 = pin.SCL_1
+
+D4 = pin.J04
+D5 = pin.N01
+D6 = pin.EE02
+D7 = pin.Y03
+D8 = pin.H03
+D9 = pin.H01
+D10 = pin.H02
+D11 = pin.H00
+D12 = pin.U00
+D13 = pin.U05
+D16 = pin.W05
+D17 = pin.W04
+D18 = pin.J00
+D19 = pin.J03
+D20 = pin.J02
+D21 = pin.J01
+D22 = pin.C02
+D23 = pin.C03
+D24 = pin.V04
+D25 = pin.V02
+D26 = pin.V03
+D27 = pin.V01
+
+CE1 = D7
+CE0 = D8
+MISO = D9
+MOSI = D10
+SCLK = D11
+SCK = D11
diff --git a/src/adafruit_blinka/board/orangepi/orangepizero2.py b/src/adafruit_blinka/board/orangepi/orangepizero2.py
new file mode 100644 (file)
index 0000000..8fb2705
--- /dev/null
@@ -0,0 +1,35 @@
+"""Pin definitions for the Orange Pi Zero 2."""
+
+from adafruit_blinka.microcontroller.allwinner.h616 import pin
+
+PH5 = pin.PH5
+SDA = pin.PH5
+PH4 = pin.PH4
+SCL = pin.PH4
+PC9 = pin.PC9
+
+PH3 = pin.PH3
+UART5_RX = pin.PH3
+PH2 = pin.PH2
+UART5_TX = pin.PH2
+PC8 = pin.PC8
+
+PC10 = pin.PC10
+PC11 = pin.PC11
+PC6 = pin.PC6
+PC5 = pin.PC5
+
+PH9 = pin.PH9
+SPI1_CS = pin.PH9
+PH6 = pin.PH6
+SPI1_CLK = pin.PH6
+PC7 = pin.PC7
+
+PC14 = pin.PC14
+
+PC15 = pin.PC15
+
+
+SCLK = pin.PH6
+MOSI = pin.PH7
+MISO = pin.PH8
diff --git a/src/adafruit_blinka/board/orangepi/orangepizeroplus.py b/src/adafruit_blinka/board/orangepi/orangepizeroplus.py
new file mode 100644 (file)
index 0000000..36ed7f3
--- /dev/null
@@ -0,0 +1,38 @@
+"""Pin definitions for the Orange Pi Zero Plus."""
+
+from adafruit_blinka.microcontroller.allwinner.h5 import pin
+
+PA12 = pin.PA12
+SDA = pin.PA12
+PA11 = pin.PA11
+SCL = pin.PA11
+PA6 = pin.PA6
+PWM1 = pin.PA6
+PA1 = pin.PA1
+UART2_RX = pin.PA1
+PA0 = pin.PA0
+UART2_TX = pin.PA0
+PA3 = pin.PA3
+UART2_CTS = pin.PA3
+PA15 = pin.PA15
+PA16 = pin.PA16
+PA14 = pin.PA14
+SPI1_CLK = pin.PA14
+PG6 = pin.PG6
+UART1_TX = pin.PG6
+PG7 = pin.PG7
+UART1_RX = pin.PG7
+PA7 = pin.PA7
+PA19 = pin.PA19
+TWI1_SDA = pin.PA19
+PA18 = pin.PA18
+TWI1_SCK = pin.PA18
+PA2 = pin.PA2
+UART2_RTS = pin.PA2
+PA13 = pin.PA13
+SPI1_CS = pin.PA13
+PA10 = pin.PA10
+
+SCLK = pin.PA14
+MOSI = pin.PA15
+MISO = pin.PA16
diff --git a/src/adafruit_blinka/board/orangepi/orangepizeroplus2h5.py b/src/adafruit_blinka/board/orangepi/orangepizeroplus2h5.py
new file mode 100644 (file)
index 0000000..c82b692
--- /dev/null
@@ -0,0 +1,35 @@
+"""Pin definitions for the Orange Pi Zero Plus 2 H5."""
+
+from adafruit_blinka.microcontroller.allwinner.h5 import pin
+
+PA12 = pin.PA12
+SDA = pin.PA12
+PA11 = pin.PA11
+SCL = pin.PA11
+PA6 = pin.PA6
+PWM1 = pin.PA6
+PA1 = pin.PA1
+UART2_RX = pin.PA1
+PA0 = pin.PA0
+UART2_TX = pin.PA0
+PA3 = pin.PA3
+UART2_CTS = pin.PA3
+PD11 = pin.PD11
+PD14 = pin.PD14
+PL0 = pin.PL0
+PL1 = pin.PL1
+
+PA13 = pin.PA13
+SPI1_CS = pin.PA13
+PA14 = pin.PA14
+SPI1_CLK = pin.PA14
+PA2 = pin.PA2
+UART2_RTS = pin.PA2
+PA18 = pin.PA18
+TWI1_SCK = pin.PA18
+PA19 = pin.PA19
+TWI1_SDA = pin.PA19
+
+SCLK = pin.PA14
+MOSI = pin.PA15
+MISO = pin.PA16
diff --git a/src/adafruit_blinka/board/pineH64.py b/src/adafruit_blinka/board/pineH64.py
new file mode 100644 (file)
index 0000000..9a51362
--- /dev/null
@@ -0,0 +1,41 @@
+"""Pin definitions for the PineH64."""
+
+from adafruit_blinka.microcontroller.allwinner.h6 import pin
+
+D2 = pin.PD26
+D3 = pin.PD25
+D4 = pin.PL8
+D5 = pin.PH2
+D6 = pin.PG14
+D7 = pin.PC16
+D8 = pin.PH3
+D9 = pin.PH6
+D10 = pin.PH5
+D11 = pin.PH4
+D12 = pin.PD22
+D13 = pin.PD21
+D14 = pin.PD19
+D15 = pin.PD20
+D16 = pin.PD24
+D17 = pin.PL9
+D18 = pin.PG11
+D19 = pin.PG10
+D21 = pin.PG12
+D22 = pin.PG13
+D23 = pin.PD16
+D24 = pin.PD17
+D25 = pin.PD18
+D26 = pin.PD23
+D27 = pin.PD14
+
+SDA = D2
+SCL = D3
+
+SCLK = D11
+MOSI = D10
+MISO = D9
+CS = D8
+SCK = SCLK
+
+UART_TX = D14
+UART_RX = D15
index 4c5eb10cb775aac5f39c9f5cd1b2f71a24054cb0..14ed95758a781156d041fb1bd06751384f04f84c 100755 (executable)
@@ -1,6 +1,6 @@
 """PyBoard pin names"""
 
-from adafruit_blinka.microcontroller.stm32 import pin
+from adafruit_blinka.microcontroller.stm32.stm32f405 import pin
 
 X1 = pin.A0
 X2 = pin.A1
diff --git a/src/adafruit_blinka/board/radxa/rockpi4.py b/src/adafruit_blinka/board/radxa/rockpi4.py
new file mode 100644 (file)
index 0000000..e327ff3
--- /dev/null
@@ -0,0 +1,62 @@
+"""Pin definitions for the Rock Pi 4."""
+
+from adafruit_blinka.microcontroller.rockchip.rk3399 import pin
+
+D3 = pin.GPIO2_A7  # /I2C7_SDA/PIN 71/
+D5 = pin.GPIO2_B0  # /I2C7_SCL/PIN 72/
+D7 = pin.GPIO2_B3  # /SPI2_CLK/PIN 75/
+D8 = pin.GPIO4_C4  # /UART2_TXD/PIN 148/
+D10 = pin.GPIO4_C3  # /UART2_RXD/PIN 147/
+D11 = pin.GPIO4_C2  # /PWM0/PIN 146/
+D13 = pin.GPIO4_C6  # /PWM1/PIN 150/
+D15 = pin.GPIO4_C5  # /SPDIF_TX/PIN 149/
+D16 = pin.GPIO4_D2  # /PIN 154/
+D17 = pin.GPIO4_D4  # /PIN 156/
+D19 = pin.GPIO1_B0  # /UART4_TXD/SPI1_TXD/PIN 40/
+D21 = pin.GPIO1_A7  # /UART4_RXD/SPI1_RXD/PIN 39/
+D22 = pin.GPIO4_D5  # /PIN 157/
+D23 = pin.GPIO1_B1  # /SPI1_CLK/PIN 41/
+D24 = pin.GPIO1_B2  # /SPI1_CS/PIN 42/
+D27 = pin.GPIO2_A0  # /I2C2_SDA/PIN 64/
+D28 = pin.GPIO2_A1  # /I2C2_SCL/PIN 65/
+D29 = pin.GPIO2_B2  # /I2C6_SCL/SPI2_TXD/PIN 74/
+D31 = pin.GPIO2_B1  # /I2C6_SDA/SPI2_RXD/PIN 73/
+D32 = pin.GPIO3_C0  # /SPDIF_TX/UART3_CTS/PIN 112/
+D33 = pin.GPIO2_B4  # /SPI2_CS/PIN 76/
+D35 = pin.GPIO4_A5  # /I2S1_LRCK_TX/PIN 133/
+D36 = pin.GPIO4_A4  # /I2S1_LRCK_RX/PIN 132/
+D37 = pin.GPIO4_D6  # /PIN 158/
+D38 = pin.GPIO4_A6  # /I2S1_SDI/PIN 134/
+D40 = pin.GPIO4_A7  # /I2S1_SDO/PIN 135/
+
+SDA2 = D27
+SCL2 = D28
+
+SDA6 = D31
+SCL6 = D29
+
+SDA7 = D3
+SCL7 = D5
+
+SDA = SDA2
+SCL = SCL2
+
+SCLK = D7
+MOSI = D29
+MISO = D31
+CS = D33
+SCK = SCLK
+
+UART2_TX = D8
+UART2_RX = D10
+
+UART4_TX = D19
+UART4_RX = D21
+
+UART_TX = UART2_TX
+UART_RX = UART2_RX
+
+PWM0 = pin.PWM0
+PWM1 = pin.PWM1
+
+ADC_IN0 = pin.ADC_IN0
index e11574fd5c33dae6df78e9cb153e3796a84d1023..bf147d7b98108ad9cb55ac61bce081708d85c1de 100644 (file)
@@ -19,8 +19,11 @@ D24 = pin.GPIO2_B1
 D25 = pin.GPIO2_A7
 D27 = pin.GPIO0_C0
 
-SDA = pin.I2C1_SDA
-SCL = pin.I2C1_SCL
+SDA0 = pin.I2C0_SDA
+SCL0 = pin.I2C0_SCL
+
+SDA1 = pin.I2C1_SDA
+SCL1 = pin.I2C1_SCL
 
 SCL2 = pin.I2C2_SCL
 SDA2 = pin.I2C2_SDA
@@ -28,6 +31,9 @@ SDA2 = pin.I2C2_SDA
 SCL3 = pin.I2C3_SCL
 SDA3 = pin.I2C3_SDA
 
+SDA = SDA1
+SCL = SCL1
+
 SCLK = pin.SPI2_SCLK
 MOSI = pin.SPI2_MOSI
 MISO = pin.SPI2_MISO
diff --git a/src/adafruit_blinka/board/soPine.py b/src/adafruit_blinka/board/soPine.py
new file mode 100644 (file)
index 0000000..00ba5b6
--- /dev/null
@@ -0,0 +1,51 @@
+"""Pin definitions for the SoPine."""
+
+from adafruit_blinka.microcontroller.allwinner.a64 import pin
+
+D2 = pin.PH3
+D3 = pin.PH2
+D4 = pin.PL10
+D5 = pin.PH5
+D6 = pin.PH6
+D7 = pin.PH7
+D8 = pin.PC3
+D9 = pin.PC1
+D10 = pin.PC0
+D11 = pin.PC2
+D12 = pin.PC4
+D13 = pin.PC5
+D14 = pin.PB0
+D15 = pin.PB1
+D16 = pin.PC6
+D17 = pin.PC7
+D18 = pin.PC8
+D19 = pin.PC9
+D20 = pin.PC10
+D21 = pin.PC11
+D22 = pin.PC12
+D23 = pin.PC13
+D24 = pin.PC14
+D25 = pin.PC15
+D26 = pin.PC16
+D27 = pin.PH9
+
+SDA = D2
+SCL = D3
+
+SCL2 = pin.PL8
+SDA2 = pin.PL9
+
+SCLK = D11
+MOSI = D10
+MISO = D9
+CS = D8
+SCK = SCLK
+
+UART_TX = D14
+UART_RX = D15
+
+UART3_TX = pin.PD0
+UART3_RX = pin.PD1
+
+UART4_TX = pin.PD2
+UART4_RX = pin.PD3
diff --git a/src/adafruit_blinka/board/stm32/__init__.py b/src/adafruit_blinka/board/stm32/__init__.py
new file mode 100644 (file)
index 0000000..d0e9d45
--- /dev/null
@@ -0,0 +1 @@
+"""Boards definition from STM32"""
diff --git a/src/adafruit_blinka/board/stm32/stm32mp157c_dk2.py b/src/adafruit_blinka/board/stm32/stm32mp157c_dk2.py
new file mode 100644 (file)
index 0000000..2f8cde1
--- /dev/null
@@ -0,0 +1,49 @@
+"""Pin definitions for the STM32MP157C Development Kit 2."""
+
+from adafruit_blinka.microcontroller.stm32.stm32mp157 import pin
+
+D2 = pin.PA12
+D3 = pin.PA11
+D4 = pin.PA8
+D5 = pin.PG2
+D6 = pin.PH11
+D7 = pin.PF3
+D8 = pin.PF6
+D9 = pin.PF8
+D10 = pin.PF9
+D11 = pin.PF7
+D12 = pin.PD13
+D13 = pin.PC7
+D14 = pin.PB10
+D15 = pin.PB12
+D16 = pin.PB13
+D17 = pin.PG8
+D18 = pin.PI5
+D19 = pin.PI7
+D20 = pin.PI6
+D21 = pin.PF11
+D22 = pin.PG15
+D23 = pin.PF1
+D24 = pin.PF0
+D25 = pin.PF4
+D26 = pin.PF5
+D27 = pin.PD7
+
+SDA = D2
+SCL = D3
+
+SDA1 = pin.PF15
+SCL1 = pin.PD12
+
+SCLK = D11
+MOSI = D10
+MISO = D9
+
+CE0 = D8
+CE1 = D7
+
+CS = CE0
+SCK = SCLK
+
+UART_TX = D14
+UART_RX = D15
diff --git a/src/adafruit_blinka/board/udoo_x86ultra.py b/src/adafruit_blinka/board/udoo_x86ultra.py
new file mode 100644 (file)
index 0000000..744d774
--- /dev/null
@@ -0,0 +1,70 @@
+"""Pin definitions for Udoo x86 Ultra
+(should work for Ultra and Ultra II)
+
+There are 2 naming systems.  A Digital Pin system which includes
+the arduino chip (Leonardo or 101).  The Braswell #s start at 16 and
+is documented in the diagram and text for linux version later than 4.15 in:
+https://www.udoo.org/docs-x86II/Introduction/Introduction.html
+The other is based on the hardware manual:
+https://udoo.org/download/files/UDOO_X86/Doc/UDOO_X86II_MANUAL.pdf
+
+This will use the D system based on the diagram in the user guide
+
+i2c use i2c(board.I2C0_SCL, board_I2C0_SDA) or i2c(board.I2C1_SCL, board_I2C1_SDA)
+for the i2c(board.SCL, board.SCL) in the examples
+
+UART use pyserial not busio
+"""
+
+from adafruit_blinka.microcontroller.pentium.n3710 import pin
+
+# Connector CN15
+D16 = pin.UART1_RTS
+D17 = pin.UART1_CTS
+D18 = pin.UART1_TXD
+D19 = pin.UART1_RXD
+D20 = pin.UART2_RTS
+D21 = pin.UART2_CTS
+D22 = pin.UART2_TXD
+D23 = pin.UART2_RXD
+
+# Connector CN13 LPC interface
+D24 = pin.GPIO_275
+D25 = pin.GPIO_280
+D26 = pin.GPIO_273
+D27 = pin.GPIO_278
+D28 = pin.GPIO_276
+D29 = pin.GPIO_279
+D30 = pin.GPIO_307
+
+# Connector CN14
+D34 = pin.I2C0_SCL
+D35 = pin.I2C0_SDA
+
+D36 = pin.GPIO_492
+D37 = pin.GPIO_490
+
+D38 = pin.I2C1_SCL
+D39 = pin.I2C1_SDA
+
+# Connector CN12 SDIO SD/MMC interfaces
+D40 = pin.GPIO_358
+D41 = pin.GPIO_243
+D42 = pin.GPIO_249
+D43 = pin.GPIO_246
+D44 = pin.GPIO_253
+D45 = pin.GPIO_250
+D46 = pin.GPIO_247
+
+# aliases
+UART1_RX = D19
+UART1_TX = D18
+
+UART2_RX = D23
+UART2_TX = D22
+
+I2C0_SCL = D34  # labeled on diagram as I2C1, hardware manual port 0
+I2C0_SDA = D35  # i2cdetect-l lists it as i2c-0
+
+I2C1_SCL = D38  # Labeled on diagram as I2C2, hardware manual port 5
+I2C1_SCL = D39  # i2cdetect lists it as i2c-1
index 9be7d1a666c3d92d5028dd24a9e0202565995b3b..0bed0510fc85bb4de8f7d9703cf324fa3a66c12e 100644 (file)
@@ -55,6 +55,8 @@ PG11 = Pin(203)
 PG12 = Pin(204)
 PG13 = Pin(205)
 
+PL2 = Pin((1, 2))
+PL4 = Pin((1, 4))
 
 i2cPorts = ((0, TWI0_SCL, TWI0_SDA),)
 # ordered as spiId, sckId, mosiId, misoId
diff --git a/src/adafruit_blinka/microcontroller/allwinner/h5/__init__.py b/src/adafruit_blinka/microcontroller/allwinner/h5/__init__.py
new file mode 100644 (file)
index 0000000..d5658ba
--- /dev/null
@@ -0,0 +1 @@
+"""Definition for the AllWinner H5 chip"""
diff --git a/src/adafruit_blinka/microcontroller/allwinner/h5/pin.py b/src/adafruit_blinka/microcontroller/allwinner/h5/pin.py
new file mode 100644 (file)
index 0000000..5ab66e8
--- /dev/null
@@ -0,0 +1,69 @@
+"""Allwinner H5 pin names"""
+from adafruit_blinka.microcontroller.generic_linux.libgpiod_pin import Pin
+
+PA0 = Pin((1, 0))
+UART2_TX = PA0
+PA1 = Pin((1, 1))
+UART2_RX = PA1
+PA2 = Pin((1, 2))
+PA3 = Pin((1, 3))
+PA6 = Pin((1, 6))
+PA7 = Pin((1, 7))
+PA8 = Pin((1, 8))
+PA9 = Pin((1, 9))
+PA10 = Pin((1, 10))
+PA11 = Pin((1, 11))
+TWI0_SCL = PA11
+PA12 = Pin((1, 12))
+TWI0_SDA = PA12
+PA13 = Pin((1, 13))
+UART3_TX = PA13
+PA14 = Pin((1, 14))
+UART3_RX = PA14
+SPI1_SCLK = PA14
+PA15 = Pin((1, 15))
+SPI1_MOSI = PA15
+PA16 = Pin((1, 16))
+SPI1_MISO = PA16
+PA17 = Pin((1, 17))
+PA18 = Pin((1, 18))
+PA19 = Pin((1, 19))
+PA20 = Pin((1, 20))
+PA21 = Pin((1, 21))
+
+PC0 = Pin((1, 64))
+SPI0_MOSI = PC0
+PC1 = Pin((1, 65))
+SPI0_MISO = PC1
+PC2 = Pin((1, 66))
+SPI0_SCLK = PC2
+PC3 = Pin((1, 67))
+SPI0_CS = PC3
+PC4 = Pin((1, 68))
+PC7 = Pin((1, 71))
+
+PD11 = Pin((1, 107))
+PD14 = Pin((1, 110))
+
+PG6 = Pin((1, 198))
+UART1_TX = PG6
+PG7 = Pin((1, 199))
+UART1_RX = PG7
+PG8 = Pin((1, 200))
+PG9 = Pin((1, 201))
+PG10 = Pin((1, 202))
+PG11 = Pin((1, 203))
+PG12 = Pin((1, 204))
+PG13 = Pin((1, 205))
+
+PL0 = Pin((0, 0))
+PL1 = Pin((0, 1))
+
+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),)
diff --git a/src/adafruit_blinka/microcontroller/allwinner/h6/__init__.py b/src/adafruit_blinka/microcontroller/allwinner/h6/__init__.py
new file mode 100644 (file)
index 0000000..0eabf00
--- /dev/null
@@ -0,0 +1 @@
+"""Definition for the AllWinner H6 chip"""
diff --git a/src/adafruit_blinka/microcontroller/allwinner/h6/pin.py b/src/adafruit_blinka/microcontroller/allwinner/h6/pin.py
new file mode 100644 (file)
index 0000000..af944e3
--- /dev/null
@@ -0,0 +1,47 @@
+"""Allwinner H6 Pin Names"""
+from adafruit_blinka.microcontroller.generic_linux.libgpiod_pin import Pin
+
+PC16 = Pin((1, 79))
+
+PD14 = Pin((1, 110))
+PD15 = Pin((1, 111))
+PD16 = Pin((1, 112))
+PD17 = Pin((1, 113))
+PD18 = Pin((1, 114))
+PD19 = Pin((1, 115))
+UART2_TX = PD19
+PD20 = Pin((1, 116))
+UART2_RX = PD20
+PD21 = Pin((1, 117))
+PD22 = Pin((1, 118))
+PD23 = Pin((1, 119))
+PD24 = Pin((1, 120))
+PD25 = Pin((1, 121))
+TWI0_SCL = PD25
+PD26 = Pin((1, 122))
+TWI0_SDA = PD26
+
+PG10 = Pin((1, 202))
+PG11 = Pin((1, 203))
+PG12 = Pin((1, 204))
+PG13 = Pin((1, 205))
+PG14 = Pin((1, 206))
+
+PH2 = Pin((1, 226))
+PH3 = Pin((1, 227))
+SPI1_CS = PH3
+PH4 = Pin((1, 228))
+SPI1_SCLK = PH4
+PH5 = Pin((1, 229))
+SPI1_MOSI = PH5
+PH6 = Pin((1, 230))
+SPI1_MISO = PH6
+PH8 = Pin((1, 230))
+PH9 = Pin((1, 231))
+
+PL8 = Pin((1, 360))
+PL9 = Pin((1, 361))
+
+i2cPorts = ((0, TWI0_SCL, TWI0_SDA),)
+spiPorts = ((0, SPI1_SCLK, SPI1_MOSI, SPI1_MISO),)
+uartPorts = ((2, UART2_TX, UART2_RX),)
diff --git a/src/adafruit_blinka/microcontroller/allwinner/h616/__init__.py b/src/adafruit_blinka/microcontroller/allwinner/h616/__init__.py
new file mode 100644 (file)
index 0000000..82e66ce
--- /dev/null
@@ -0,0 +1 @@
+"""Definition for the AllWinner H616 chip"""
diff --git a/src/adafruit_blinka/microcontroller/allwinner/h616/pin.py b/src/adafruit_blinka/microcontroller/allwinner/h616/pin.py
new file mode 100644 (file)
index 0000000..160aee2
--- /dev/null
@@ -0,0 +1,105 @@
+"""Allwinner H616 Pin Names"""
+from adafruit_blinka.microcontroller.generic_linux.libgpiod_pin import Pin
+
+PC0 = Pin((1, 64))
+SPI0_CLK = PC0
+PC1 = Pin((1, 65))
+PC2 = Pin((1, 66))
+SPI0_MOSI = PC2
+PC3 = Pin((1, 67))
+SPI0_CS0 = PC3
+PC4 = Pin((1, 68))
+SPI0_MISO = PC4
+PC5 = Pin((1, 69))
+PC6 = Pin((1, 70))
+PC7 = Pin((1, 71))
+PC8 = Pin((1, 72))
+PC9 = Pin((1, 73))
+PC10 = Pin((1, 74))
+PC11 = Pin((1, 75))
+PC12 = Pin((1, 76))
+PC13 = Pin((1, 77))
+PC14 = Pin((1, 78))
+PC15 = Pin((1, 79))
+
+PF0 = Pin((1, 160))
+PF1 = Pin((1, 161))
+PF2 = Pin((1, 162))
+PF3 = Pin((1, 163))
+PF4 = Pin((1, 164))
+PF5 = Pin((1, 165))
+PF6 = Pin((1, 166))
+
+PG0 = Pin((1, 192))
+PG1 = Pin((1, 193))
+PG2 = Pin((1, 194))
+PG3 = Pin((1, 195))
+PG4 = Pin((1, 196))
+PG5 = Pin((1, 197))
+PG6 = Pin((1, 198))
+PG7 = Pin((1, 199))
+PG8 = Pin((1, 200))
+PG9 = Pin((1, 201))
+PG10 = Pin((1, 202))
+PG11 = Pin((1, 203))
+PG12 = Pin((1, 204))
+PG13 = Pin((1, 205))
+PG14 = Pin((1, 206))
+PG15 = Pin((1, 207))
+PG16 = Pin((1, 208))
+PG17 = Pin((1, 209))
+PG18 = Pin((1, 210))
+PG19 = Pin((1, 211))
+
+PH0 = Pin((1, 224))
+PH1 = Pin((1, 225))
+PH2 = Pin((1, 226))
+UART5_TX = PH2
+PH3 = Pin((1, 227))
+UART5_RX = PH3
+PH4 = Pin((1, 228))
+TWI3_SCL = PH4
+PH5 = Pin((1, 229))
+UART2_TX = PH5
+TWI3_SDA = PH5
+SPI1_CS0 = PH5
+PH6 = Pin((1, 230))
+UART2_RX = PH6
+SPI1_CLK = PH6
+PH7 = Pin((1, 231))
+SPI1_MOSI = PH7
+PH8 = Pin((1, 232))
+SPI1_MISO = PH8
+PH9 = Pin((1, 233))
+SPI1_CS1 = PH9
+PH10 = Pin((1, 234))
+
+PI0 = Pin((1, 256))
+PI1 = Pin((1, 257))
+PI2 = Pin((1, 258))
+PI3 = Pin((1, 259))
+PI4 = Pin((1, 260))
+PI5 = Pin((1, 261))
+PI6 = Pin((1, 262))
+PI7 = Pin((1, 263))
+PI8 = Pin((1, 264))
+PI9 = Pin((1, 265))
+PI10 = Pin((1, 266))
+PI11 = Pin((1, 267))
+PI12 = Pin((1, 268))
+PI13 = Pin((1, 269))
+PI14 = Pin((1, 270))
+PI15 = Pin((1, 271))
+PI16 = Pin((1, 272))
+
+i2cPorts = ((3, TWI3_SCL, TWI3_SDA),)
+# ordered as spiId, sckId, mosiId, misoId
+spiPorts = (
+    (0, SPI0_CLK, SPI0_MOSI, SPI0_MISO),
+    (1, SPI1_CLK, SPI1_MOSI, SPI1_MISO),
+)
+# ordered as uartId, txId, rxId
+uartPorts = (
+    (2, UART2_TX, UART2_RX),
+    (5, UART5_TX, UART5_RX),
+)
index 2ba135927da79d86e24ae76fd758e9fed9383c63..b99e1cc8000ef88293ecb81146fd8e3b49bc6bbf 100644 (file)
@@ -9,7 +9,7 @@ import os
 try:
     from microcontroller.pin import pwmOuts
 except ImportError:
-    raise RuntimeError("No PWM outputs defined for this board")
+    raise RuntimeError("No PWM outputs defined for this board") from ImportError
 
 # pylint: disable=unnecessary-pass
 class PWMError(IOError):
@@ -105,7 +105,7 @@ class PWMOut:
                 ) as f_export:
                     f_export.write("%d\n" % self._pwmpin)
             except IOError as e:
-                raise PWMError(e.errno, "Exporting PWM pin: " + e.strerror)
+                raise PWMError(e.errno, "Exporting PWM pin: " + e.strerror) from IOError
 
         # Look up the period, for fast duty cycle updates
         self._period = self._get_period()
@@ -135,7 +135,9 @@ class PWMOut:
                     ) as f_unexport:
                         f_unexport.write("%d\n" % self._pwmpin)
                 except IOError as e:
-                    raise PWMError(e.errno, "Unexporting PWM pin: " + e.strerror)
+                    raise PWMError(
+                        e.errno, "Unexporting PWM pin: " + e.strerror
+                    ) from IOError
         except Exception as e:
             # due to a race condition for which I have not yet been
             # able to find the root cause, deinit() often fails
@@ -192,7 +194,9 @@ class PWMOut:
         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
+            ) from ValueError
 
         # Convert period from nanoseconds to seconds
         period = period_ns / 1e9
@@ -230,7 +234,9 @@ class PWMOut:
         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
+            ) from ValueError
 
         # Convert duty cycle from nanoseconds to seconds
         duty_cycle = duty_cycle_ns / 1e9
index 165bca71db19a9a3b4c7340212f4aaf5f7ca5b9d..82fa6ea267b07072b1c629589cdea8b71c8a8ed0 100644 (file)
@@ -9,8 +9,8 @@ Linux kernel 5.4.y (mainline)
 """
 
 import re
-from adafruit_blinka.microcontroller.generic_linux.libgpiod_pin import Pin
 import gpiod
+from adafruit_blinka.microcontroller.generic_linux.libgpiod_pin import Pin
 
 chip0 = gpiod.Chip("0")
 chip1 = gpiod.Chip("1")
index 813a51a092706d6d54b4f86833dce9c03c4171b6..6c0726f8392910650a0f1103e6dc07fc5bf602c6 100644 (file)
@@ -16,18 +16,24 @@ LED_STRIP = None  # We manage the color order within the neopixel library
 # a 'static' object that we will use to manage our PWM DMA channel
 # we only support one LED strip per raspi
 _led_strip = None
+_buf = None
 
 
 def neopixel_write(gpio, buf):
     """NeoPixel Writing Function"""
     global _led_strip  # we'll have one strip we init if its not at first
+    global _buf  # we save a reference to the buf, and if it changes we will cleanup and re-init.
+
+    if _led_strip is None or buf is not _buf:
+        # This is safe to call since it doesn't do anything if _led_strip is None
+        neopixel_cleanup()
 
-    if _led_strip is None:
         # Create a ws2811_t structure from the LED configuration.
         # Note that this structure will be created on the heap so you
         # need to be careful that you delete its memory by calling
         # delete_ws2811_t when it's not needed.
         _led_strip = ws.new_ws2811_t()
+        _buf = buf
 
         # Initialize all channels to off
         for channum in range(2):
index e95364c6febcbf94a01da1657ad114e2f710bcbb..5022366a7d4dd1b299b5b17301d5b73beb0d2178 100644 (file)
@@ -147,8 +147,10 @@ spiPorts = (
 # ordered as uartId, txId, rxId
 uartPorts = ((1, TXD, RXD),)
 
+# These are the known hardware I2C ports / pins.
+# For software I2C ports created with the i2c-gpio overlay, see:
+#     https://github.com/adafruit/Adafruit_Python_Extended_Bus
 i2cPorts = (
-    (3, SCL, SDA),
     (1, SCL, SDA),
     (0, D1, D0),  # both pi 1 and pi 2 i2c ports!
 )
diff --git a/src/adafruit_blinka/microcontroller/bcm283x/pulseio/PWMOut.py b/src/adafruit_blinka/microcontroller/bcm283x/pulseio/PWMOut.py
new file mode 100644 (file)
index 0000000..65f269f
--- /dev/null
@@ -0,0 +1,162 @@
+"""Custom PWMOut Wrapper for Rpi.GPIO PWM Class"""
+import RPi.GPIO as GPIO
+
+GPIO.setmode(GPIO.BCM)  # Use BCM pins D4 = GPIO #4
+GPIO.setwarnings(False)  # shh!
+
+
+# pylint: disable=unnecessary-pass
+class PWMError(IOError):
+    """Base class for PWM errors."""
+
+    pass
+
+
+# pylint: enable=unnecessary-pass
+
+
+class PWMOut:
+    """Pulse Width Modulation Output Class"""
+
+    def __init__(self, pin, *, frequency=500, duty_cycle=0, variable_frequency=False):
+        self._pwmpin = None
+        self._period = 0
+        self._open(pin, duty_cycle, frequency, variable_frequency)
+
+    def __del__(self):
+        self.deinit()
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, t, value, traceback):
+        self.deinit()
+
+    def _open(self, pin, duty=0, freq=500, variable_frequency=False):
+        self._pin = pin
+        GPIO.setup(pin.id, GPIO.OUT)
+        self._pwmpin = GPIO.PWM(pin.id, freq)
+
+        if variable_frequency:
+            print("Variable Frequency is not supported, continuing without it...")
+
+        # set frequency
+        self.frequency = freq
+        # set duty
+        self.duty_cycle = duty
+
+        self.enabled = True
+
+    def deinit(self):
+        """Deinit the PWM."""
+        if self._pwmpin is not None:
+            self._pwmpin.stop()
+            GPIO.cleanup(self._pin.id)
+            self._pwmpin = None
+
+    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."
+            )
+
+    @property
+    def period(self):
+        """Get or set the PWM's output period in seconds.
+
+        Raises:
+            PWMError: if an I/O or OS error occurs.
+            TypeError: if value type is not int or float.
+
+        :type: int, float
+        """
+        return 1.0 / self.frequency
+
+    @period.setter
+    def period(self, period):
+        if not isinstance(period, (int, float)):
+            raise TypeError("Invalid period type, should be int or float.")
+
+        self.frequency = 1.0 / period
+
+    @property
+    def duty_cycle(self):
+        """Get or set the PWM's output duty cycle which is the fraction of
+        each pulse which is high. 16-bit
+
+        Raises:
+            PWMError: if an I/O or OS error occurs.
+            TypeError: if value type is not int or float.
+            ValueError: if value is out of bounds of 0.0 to 1.0.
+
+        :type: int, float
+        """
+        return int(self._duty_cycle * 65535)
+
+    @duty_cycle.setter
+    def duty_cycle(self, duty_cycle):
+        if not isinstance(duty_cycle, (int, float)):
+            raise TypeError("Invalid duty cycle type, should be int or float.")
+
+        if not 0 <= duty_cycle <= 65535:
+            raise ValueError("Invalid duty cycle value, should be between 0 and 65535")
+
+        # convert from 16-bit
+        duty_cycle /= 65535.0
+
+        self._duty_cycle = duty_cycle
+        self._pwmpin.ChangeDutyCycle(round(self._duty_cycle * 100))
+
+    @property
+    def frequency(self):
+        """Get or set the PWM's output frequency in Hertz.
+
+        Raises:
+            PWMError: if an I/O or OS error occurs.
+            TypeError: if value type is not int or float.
+
+        :type: int, float
+        """
+
+        return self._frequency
+
+    @frequency.setter
+    def frequency(self, frequency):
+        if not isinstance(frequency, (int, float)):
+            raise TypeError("Invalid frequency type, should be int or float.")
+
+        self._pwmpin.ChangeFrequency(round(frequency))
+        self._frequency = frequency
+
+    @property
+    def enabled(self):
+        """Get or set the PWM's output enabled state.
+
+        Raises:
+            PWMError: if an I/O or OS error occurs.
+            TypeError: if value type is not bool.
+
+        :type: bool
+        """
+        return self._enabled
+
+    @enabled.setter
+    def enabled(self, value):
+        if not isinstance(value, bool):
+            raise TypeError("Invalid enabled type, should be string.")
+
+        if value:
+            self._pwmpin.start(round(self._duty_cycle * 100))
+        else:
+            self._pwmpin.stop()
+
+        self._enabled = value
+
+    # String representation
+    def __str__(self):
+        return "pin %s (freq=%f Hz, duty_cycle=%f%%)" % (
+            self._pin,
+            self.frequency,
+            self.duty_cycle,
+        )
index d2390f6fed489d77f040b9735408ef42981d9084..19dc98f32089364b6e266712f07ce39038dda5e1 100644 (file)
@@ -45,7 +45,9 @@ class PulseIn:
                 print("Message Queue Key: ", self._mq.key)
             queues.append(self._mq)
         except sysv_ipc.ExistentialError:
-            raise RuntimeError("Message queue creation failed")
+            raise RuntimeError(
+                "Message queue creation failed"
+            ) from sysv_ipc.ExistentialError
 
         dir_path = os.path.dirname(os.path.realpath(__file__))
         cmd = [
@@ -68,26 +70,29 @@ class PulseIn:
         # wait for it to start up
         if DEBUG:
             print("Waiting for startup success message from subprocess")
-        message = self._wait_receive_msg()
+        message = self._wait_receive_msg(timeout=0.25)
         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):
+    def _wait_receive_msg(self, timeout=0, 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=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. Make sure libgpiod is installed."
-        )
+        if timeout > 0:
+            stamp = time.monotonic()
+            while (time.monotonic() - stamp) < timeout:
+                try:
+                    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. Make sure libgpiod is installed."
+            )
+        message = self._mq.receive(block=True, type=type)
+        return message
 
     # pylint: enable=redefined-builtin
 
diff --git a/src/adafruit_blinka/microcontroller/dra74x/__init__.py b/src/adafruit_blinka/microcontroller/dra74x/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/adafruit_blinka/microcontroller/dra74x/pin.py b/src/adafruit_blinka/microcontroller/dra74x/pin.py
new file mode 100644 (file)
index 0000000..28738c1
--- /dev/null
@@ -0,0 +1,185 @@
+"""DRA74x pin names"""
+from adafruit_blinka.microcontroller.generic_linux.libgpiod_pin import Pin
+
+# BeagleBone AI
+# P8_1 = DGND           # DGND
+# P8_2 = DGND           # DGND
+P8_3 = Pin((0, 24))  # GPIO1_24 - GPIO_24
+P8_4 = Pin((0, 25))  # GPIO1_25 - GPIO_25
+P8_5 = Pin((6, 1))  # GPIO7_1 - GPIO_193
+P8_6 = Pin((6, 2))  # GPIO7_2 - GPIO_194
+P8_7 = Pin((5, 5))  # TIMER4 - GPIO_165
+P8_8 = Pin((5, 6))  # TIMER7 - GPIO_166
+P8_9 = Pin((5, 18))  # TIMER5 - GPIO_178
+P8_10 = Pin((5, 4))  # TIMER6 - GPIO_164
+P8_11 = Pin((2, 11))  # GPIO3_11 - GPIO_75
+P8_12 = Pin((2, 10))  # GPIO3_10 - GPIO_74
+P8_13 = Pin((3, 11))  # EHRPWM2B - GPIO_107
+P8_14 = Pin((3, 13))  # GPIO4_13 - GPIO_109
+P8_15 = Pin((3, 3))  # GPIO4_3 - GPIO_99
+P8_16 = Pin((3, 29))  # GPIO4_29 - GPIO_125
+P8_17 = Pin((7, 18))  # GPIO8_18 - GPIO_242
+P8_18 = Pin((3, 9))  # GPIO4_9 - GPIO_105
+P8_19 = Pin((3, 10))  # EHRPWM2A - GPIO_106
+P8_20 = Pin((5, 30))  # GPIO6_30 - GPIO_190
+P8_21 = Pin((5, 29))  # GPIO6_29 - GPIO_189
+P8_22 = Pin((0, 23))  # GPIO1_23 - GPIO_23
+P8_23 = Pin((0, 22))  # GPIO1_22 - GPIO_22
+P8_24 = Pin((6, 0))  # GPIO7_0 - GPIO_192
+P8_25 = Pin((5, 31))  # GPIO6_31 - GPIO_191
+P8_26 = Pin((3, 28))  # GPIO4_28 - GPIO_124
+P8_27 = Pin((3, 23))  # GPIO4_23 - GPIO_119
+P8_28 = Pin((3, 19))  # GPIO4_19 - GPIO_115
+P8_29 = Pin((3, 22))  # GPIO4_22 - GPIO_118
+P8_30 = Pin((3, 20))  # GPIO4_20 - GPIO_116
+P8_31 = Pin((7, 14))  # UART5_CTSN - GPIO_238
+P8_32 = Pin((7, 15))  # UART5_RTSN - GPIO_239
+P8_33 = Pin((7, 13))  # UART4_RTSN - GPIO_237
+P8_34 = Pin((7, 11))  # UART3_RTSN - GPIO_235
+P8_35 = Pin((7, 12))  # UART4_CTSN - GPIO_236
+P8_36 = Pin((7, 10))  # UART3_CTSN - GPIO_234
+P8_37 = Pin((7, 8))  # UART5_TXD - GPIO_232
+P8_38 = Pin((7, 9))  # UART5_RXD - GPIO_233
+P8_39 = Pin((7, 6))  # GPIO8_6 - GPIO_230
+P8_40 = Pin((7, 7))  # GPIO8_7 - GPIO_231
+P8_41 = Pin((7, 4))  # GPIO8_4 - GPIO_228
+P8_42 = Pin((7, 5))  # GPIO8_5 - GPIO_229
+P8_43 = Pin((7, 2))  # GPIO8_2 - GPIO_226
+P8_44 = Pin((7, 3))  # GPIO8_3 - GPIO_227
+P8_45 = Pin((7, 0))  # GPIO8_0 - GPIO_224
+P8_46 = Pin((7, 1))  # GPIO8_1 - GPIO_225
+
+# P9_1 = DGND           # DGND - GPIO_0
+# P9_2 = DGND           # DGND - GPIO_0
+# P9_3 = VDD_3V3        # VDD_3V3 - GPIO_0
+# P9_4 = VDD_3V3        # VDD_3V3 - GPIO_0
+# P9_5 = VDD_5V         # VDD_5V - GPIO_0
+# P9_6 = VDD_5V         # VDD_5V - GPIO_0
+# P9_7 = SYS_5V         # SYS_5V - GPIO_0
+# 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((7, 17))  # UART4_RXD - GPIO_241
+P9_12 = Pin((4, 0))  # GPIO5_0 - GPIO_128
+P9_13 = Pin((5, 12))  # UART4_TXD - GPIO_172
+P9_14 = Pin((3, 25))  # EHRPWM1A - GPIO_121
+P9_15 = Pin((2, 12))  # GPIO3_12 - GPIO_76
+P9_16 = Pin((3, 26))  # EHRPWM1B - GPIO_122
+P9_17 = Pin((6, 17))  # I2C1_SCL - GPIO_209
+P9_18 = Pin((6, 16))  # I2C1_SDA - GPIO_208
+P9_19 = Pin((6, 3))  # I2C2_SCL - GPIO_195
+P9_20 = Pin((6, 4))  # I2C2_SDA - GPIO_196
+P9_21 = Pin((2, 3))  # UART3_TXD - GPIO_67
+P9_22 = Pin((5, 19))  # UART3_RXD - GPIO_179
+P9_23 = Pin((6, 11))  # GPIO7_11 - GPIO_203
+P9_24 = Pin((5, 15))  # UART1_TXD - GPIO_175
+P9_25 = Pin((5, 17))  # GPIO6_17 - GPIO_177
+P9_26 = Pin((5, 14))  # UART1_RXD - GPIO_174
+P9_27 = Pin((3, 15))  # GPIO4_15 - GPIO_111
+P9_28 = Pin((3, 17))  # SPI1_CS0 - GPIO_113
+P9_29 = Pin((4, 11))  # SPI1_D0 - GPIO_139
+P9_30 = Pin((4, 12))  # SPI1_D1 - GPIO_140
+P9_31 = Pin((4, 10))  # SPI1_SCLK - GPIO_138
+# P9_32 = VDD_ADC       # VDD_ADC - GPIO_0
+# P9_33 = AIN4          # AIN4 - GPIO_0
+# P9_34 = GNDA_ADC      # GNDA_ADC - GPIO_0
+# P9_35 = AIN6          # AIN6 - GPIO_0
+# P9_36 = AIN5          # AIN5 - GPIO_0
+# P9_37 = AIN2          # AIN2 - GPIO_0
+# P9_38 = AIN3          # AIN3 - GPIO_0
+# P9_39 = AIN0          # AIN0 - GPIO_0
+# P9_40 = AIN1          # AIN1 - GPIO_0
+P9_41 = Pin((5, 20))  # CLKOUT2 - GPIO_180
+P9_42 = Pin((3, 18))  # GPIO4_18 - GPIO_114
+# P9_43 = DGND          # DGND - GPIO_0
+# P9_44 = DGND          # DGND - GPIO_0
+# P9_45 = DGND          # DGND - GPIO_0
+# P9_46 = DGND          # DGND - GPIO_0
+
+
+##########################################
+# User LEDs
+USR0 = Pin((2, 17))  # USR0 - GPIO3_17
+USR1 = Pin((4, 5))  # USR1 - GPIO5_5
+USR2 = Pin((2, 15))  # USR2 - GPIO3_15
+USR3 = Pin((2, 14))  # USR3 - GPIO3_14
+USR4 = Pin((2, 7))  # USR4 - GPIO3_7
+
+# I2C4
+I2C4_SCL = P9_19  # i2c4_scl
+I2C4_SDA = P9_20  # i2c4_sda
+
+# I2C5
+I2C5_SCL = P9_17  # i2c5_scl
+I2C5_SDA = P9_18  # i2c5_sda
+
+# SPI0
+SPI0_CS0 = P9_17
+SPI0_D1 = P9_18
+SPI0_D0 = P9_21
+SPI0_SCLK = P9_22
+
+# SPI1
+SPI1_CS0 = P9_28
+SPI1_CS1 = P9_42
+SPI1_SCLK = P9_31
+SPI1_D0 = P9_30
+SPI1_D1 = P9_29
+
+# UART0
+UART0_TXD = P8_44
+UART0_RXD = P8_36
+UART0_RTSn = P8_34
+UART0_CTSn = P8_45
+
+# UART3
+UART3_TXD = P9_21
+UART3_RXD = P9_22
+UART3_RTSn = P9_17
+UART3_CTSn = P9_18
+
+# UART5
+UART5_TXD = P9_13
+UART5_RXD = P9_11
+UART5_RTSn = P8_6
+UART5_CTSn = P8_5
+
+# UART8
+UART8_TXD = P8_37
+UART8_RXD = P8_38
+UART8_RTSn = P8_32
+UART8_CTSn = P8_31
+
+# UART10
+UART10_TXD = P9_24
+UART10_RXD = P9_26
+UART10_RTSn = P8_4
+UART10_CTSn = P8_3
+
+# PWM
+TIMER10 = P8_10
+TIMER11 = P8_7
+TIMER12 = P8_8
+TIMER14 = P8_9
+
+# ordered as i2cId, SCL, SDA
+i2cPorts = (
+    (3, I2C4_SCL, I2C4_SDA),  # default config
+    (4, I2C4_SCL, I2C4_SDA),  # roboticscape config
+    (3, I2C5_SCL, I2C5_SDA),  # roboticscape config
+)
+
+# ordered as spiId, sckId, mosiId, misoId
+spiPorts = (
+    (0, SPI0_SCLK, SPI0_D0, SPI0_D1),
+    (1, SPI1_SCLK, SPI1_D1, SPI1_D0),
+)
+
+# ordered as uartId, txId, rxId
+uartPorts = (
+    (0, UART0_TXD, UART0_RXD),
+    (3, UART3_TXD, UART3_RXD),
+    (5, UART5_TXD, UART5_RXD),
+    (8, UART8_TXD, UART8_RXD),
+    (10, UART10_TXD, UART10_RXD),
+)
index 6a0ea938ffe3db0a79f5ff664bdc1c857c51a9a7..dc6282abfa82ab17b9e38c796e37c0a1daeeddf9 100644 (file)
@@ -8,6 +8,9 @@ class Pin:
     OUT = 1
     LOW = 0
     HIGH = 1
+    PULL_NONE = 0
+    PULL_UP = 1
+    PULL_DOWN = 2
 
     mpsse_gpio = None
 
@@ -36,7 +39,7 @@ class Pin:
             raise RuntimeError("Can not init a None type pin.")
         # MPSSE does't have configurable internal pulls?
         if pull:
-            raise ValueError("Internal pull up/down not currently supported.")
+            raise NotImplementedError("Internal pull up/down not currently supported.")
         pin_mask = Pin.mpsse_gpio.pins | 1 << self.id
         current = Pin.mpsse_gpio.direction
         if mode == self.OUT:
index 69fe66fcbfbf1b7e085f8f6a5afc1b8b9790094c..63047003a3cbf8ed318d1c8f9ab937c37f64455e 100644 (file)
@@ -63,13 +63,15 @@ class SPI:
             chunk_end = chunk_start + self._spi.PAYLOAD_MAX_LENGTH
             self._port.write(buf[chunk_start:chunk_end])
         if rest:
-            self._port.write(buf[-1 * rest :])
+            rest_start = start + chunks * self._spi.PAYLOAD_MAX_LENGTH
+            self._port.write(buf[rest_start:end])
 
     # 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)
+        buffer_out = [write_value] * (end - start)
+        result = self._port.exchange(buffer_out, end - start, duplex=True)
         for i, b in enumerate(result):
             buf[start + i] = b
 
index 1870dfc802eb28206a1bca6c8f3ddbd0fa10d124..7be7514a9426af43188158b0da31bfa423501405 100644 (file)
@@ -25,7 +25,7 @@ class I2C:
         except FileNotFoundError:
             raise RuntimeError(
                 "I2C Bus #%d not found, check if enabled in config!" % bus_num
-            )
+            ) from RuntimeError
 
     # pylint: enable=unused-argument
 
index 4ffa5c1725da19bf4e2d049e02940f7da1e527fd..db9007a6d55d479b4322ed2a67ba2b10804f43a7 100644 (file)
@@ -5,7 +5,7 @@ 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"
-    )
+    ) from ImportError
 
 
 class Pin:
index 69044f84757a26994a360eb45fca1c91c50335a0..0986d0135b11d3407321e24e539df89d44ae5644 100644 (file)
@@ -5,7 +5,7 @@ except ImportError:
     raise ImportError(
         "Periphery Python bindings not found, please install and try again! "
         "Try running 'pip3 install python-periphery'"
-    )
+    ) from ImportError
 
 
 class Pin:
index bf6988be1033b4b7192132722ed22a195f78f0ef..e8a7376c615786a0ea759229a7886d01e947ec45 100644 (file)
@@ -13,7 +13,7 @@ from adafruit_blinka import ContextManaged
 try:
     from microcontroller.pin import analogIns
 except ImportError:
-    raise RuntimeError("No Analog Inputs defined for this board")
+    raise RuntimeError("No Analog Inputs defined for this board") from ImportError
 
 
 class AnalogIn(ContextManaged):
index ec8b6c6ab58ffd7959625cf7f25e04fdd1d31d7f..56263d39555a384178cef873328139438747af36 100644 (file)
@@ -13,7 +13,7 @@ from adafruit_blinka import ContextManaged
 try:
     from microcontroller.pin import analogOuts
 except ImportError:
-    raise RuntimeError("No Analog Outputs defined for this board")
+    raise RuntimeError("No Analog Outputs defined for this board") from ImportError
 
 
 class AnalogOut(ContextManaged):
index c5b56e69869603a83308da2255d113646688d674..50c27a7b6ca0a3d13bad10b0c413c89cbbc54ba1 100644 (file)
@@ -135,7 +135,7 @@ class Pin:
                 with open("/sys/class/gpio/export", "w") as f_export:
                     f_export.write("{:d}\n".format(self.id))
             except IOError as e:
-                raise GPIOError(e.errno, "Exporting GPIO: " + e.strerror)
+                raise GPIOError(e.errno, "Exporting GPIO: " + e.strerror) from IOError
 
             # Loop until GPIO is exported
             exported = False
@@ -164,7 +164,7 @@ class Pin:
                     ):
                         raise GPIOError(
                             e.errno, "Setting GPIO direction: " + e.strerror
-                        )
+                        ) from IOError
 
                 time.sleep(self.GPIO_OPEN_DELAY)
         else:
@@ -173,13 +173,15 @@ class Pin:
                 with open(os.path.join(gpio_path, "direction"), "w") as f_direction:
                     f_direction.write(direction.lower() + "\n")
             except IOError as e:
-                raise GPIOError(e.errno, "Setting GPIO direction: " + e.strerror)
+                raise GPIOError(
+                    e.errno, "Setting GPIO direction: " + e.strerror
+                ) from IOError
 
         # Open value
         try:
             self._fd = os.open(os.path.join(gpio_path, "value"), os.O_RDWR)
         except OSError as e:
-            raise GPIOError(e.errno, "Opening GPIO: " + e.strerror)
+            raise GPIOError(e.errno, "Opening GPIO: " + e.strerror) from OSError
 
         self._path = gpio_path
 
@@ -192,7 +194,7 @@ class Pin:
         try:
             os.close(self._fd)
         except OSError as e:
-            raise GPIOError(e.errno, "Closing GPIO: " + e.strerror)
+            raise GPIOError(e.errno, "Closing GPIO: " + e.strerror) from OSError
 
         self._fd = None
 
@@ -202,20 +204,20 @@ class Pin:
             os.write(unexport_fd, "{:d}\n".format(self.id).encode())
             os.close(unexport_fd)
         except OSError as e:
-            raise GPIOError(e.errno, "Unexporting GPIO: " + e.strerror)
+            raise GPIOError(e.errno, "Unexporting GPIO: " + e.strerror) from OSError
 
     def _read(self):
         # Read value
         try:
             buf = os.read(self._fd, 2)
         except OSError as e:
-            raise GPIOError(e.errno, "Reading GPIO: " + e.strerror)
+            raise GPIOError(e.errno, "Reading GPIO: " + e.strerror) from OSError
 
         # Rewind
         try:
             os.lseek(self._fd, 0, os.SEEK_SET)
         except OSError as e:
-            raise GPIOError(e.errno, "Rewinding GPIO: " + e.strerror)
+            raise GPIOError(e.errno, "Rewinding GPIO: " + e.strerror) from OSError
 
         if buf[0] == b"0"[0]:
             return False
@@ -235,13 +237,13 @@ class Pin:
             else:
                 os.write(self._fd, b"0\n")
         except OSError as e:
-            raise GPIOError(e.errno, "Writing GPIO: " + e.strerror)
+            raise GPIOError(e.errno, "Writing GPIO: " + e.strerror) from OSError
 
         # Rewind
         try:
             os.lseek(self._fd, 0, os.SEEK_SET)
         except OSError as e:
-            raise GPIOError(e.errno, "Rewinding GPIO: " + e.strerror)
+            raise GPIOError(e.errno, "Rewinding GPIO: " + e.strerror) from OSError
 
     @property
     def chip_name(self):
@@ -270,9 +272,13 @@ class Pin:
                 label = f_label.read()
         except (GPIOError, IOError) as e:
             if isinstance(e, IOError):
-                raise GPIOError(e.errno, "Reading gpiochip label: " + e.strerror)
+                raise GPIOError(
+                    e.errno, "Reading gpiochip label: " + e.strerror
+                ) from IOError
 
-            raise GPIOError(None, "Reading gpiochip label: " + e.strerror)
+            raise GPIOError(
+                None, "Reading gpiochip label: " + e.strerror
+            ) from GPIOError
 
         return label.strip()
 
@@ -284,7 +290,9 @@ class Pin:
             with open(os.path.join(self._path, "direction"), "r") as f_direction:
                 direction = f_direction.read()
         except IOError as e:
-            raise GPIOError(e.errno, "Getting GPIO direction: " + e.strerror)
+            raise GPIOError(
+                e.errno, "Getting GPIO direction: " + e.strerror
+            ) from IOError
 
         return direction.strip()
 
@@ -299,7 +307,9 @@ class Pin:
             with open(os.path.join(self._path, "direction"), "w") as f_direction:
                 f_direction.write(direction.lower() + "\n")
         except IOError as e:
-            raise GPIOError(e.errno, "Setting GPIO direction: " + e.strerror)
+            raise GPIOError(
+                e.errno, "Setting GPIO direction: " + e.strerror
+            ) from IOError
 
     direction = property(_get_direction, _set_direction)
 
index 6cf477c15dd63aa1e8422890504d92920d847b6d..f751b71a4a017dc3870da1e1445820b6c521e1ce 100644 (file)
@@ -5,11 +5,13 @@ License: MIT
 """
 
 import os
+from time import sleep
+from errno import EACCES
 
 try:
     from microcontroller.pin import pwmOuts
 except ImportError:
-    raise RuntimeError("No PWM outputs defined for this board")
+    raise RuntimeError("No PWM outputs defined for this board") from ImportError
 
 
 # pylint: disable=unnecessary-pass
@@ -25,6 +27,11 @@ class PWMError(IOError):
 class PWMOut:
     """Pulse Width Modulation Output Class"""
 
+    # Number of retries to check for successful PWM export on open
+    PWM_STAT_RETRIES = 10
+    # Delay between check for scucessful PWM export on open (100ms)
+    PWM_STAT_DELAY = 0.1
+
     # Sysfs paths
     _sysfs_path = "/sys/class/pwm/"
     _channel_path = "pwmchip{}"
@@ -107,7 +114,26 @@ class PWMOut:
             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)
+            raise PWMError(e.errno, "Exporting PWM pin: " + e.strerror) from IOError
+
+        # Loop until 'period' is writable, because application of udev rules
+        # after the above pin export is asynchronous.
+        # Without this loop, the following properties may not be writable yet.
+        for i in range(PWMOut.PWM_STAT_RETRIES):
+            try:
+                with open(
+                    os.path.join(
+                        channel_path, self._pin_path.format(self._pwmpin), "period"
+                    ),
+                    "w",
+                ):
+                    break
+            except IOError as e:
+                if e.errno != EACCES or (
+                    e.errno == EACCES and i == PWMOut.PWM_STAT_RETRIES - 1
+                ):
+                    raise PWMError(e.errno, "Opening PWM period: " + e.strerror) from e
+            sleep(PWMOut.PWM_STAT_DELAY)
 
         # self._set_enabled(False) # This line causes a write error when trying to enable
 
@@ -136,7 +162,9 @@ class PWMOut:
                 ) as f_unexport:
                     f_unexport.write("%d\n" % self._pwmpin)
             except IOError as e:
-                raise PWMError(e.errno, "Unexporting PWM pin: " + e.strerror)
+                raise PWMError(
+                    e.errno, "Unexporting PWM pin: " + e.strerror
+                ) from IOError
 
         self._channel = None
         self._pwmpin = None
@@ -184,7 +212,9 @@ class PWMOut:
         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
+            ) from ValueError
 
         # Convert period from nanoseconds to seconds
         period = period_ns / 1e9
@@ -222,7 +252,9 @@ class PWMOut:
         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
+            ) from ValueError
 
         # Convert duty cycle from nanoseconds to seconds
         duty_cycle = duty_cycle_ns / 1e9
index cd8f60d04076bf6ddbb152fcfc8e15f4c369eba9..df2642f681456d60dd288919f0df9b0b3417c58d 100644 (file)
@@ -7,7 +7,7 @@ class I2C:
 
     def __init__(self, *, frequency=100000):
         self._mcp2221 = mcp2221
-        self._mcp2221.i2c_configure(frequency)
+        self._mcp2221._i2c_configure(frequency)
 
     def scan(self):
         """Perform an I2C Device Scan"""
index a4a1d990a58ecd8419873c81d2cd4b62403e6a5d..0e061e62380d888880ab2a79624c4ec903bfce08 100644 (file)
@@ -6,13 +6,12 @@ import hid
 
 # Here if you need it
 MCP2221_HID_DELAY = float(os.environ.get("BLINKA_MCP2221_HID_DELAY", 0))
-# Use to set delay between reset and device reopen
+# Use to set delay between reset and device reopen. if negative, don't reset at all
 MCP2221_RESET_DELAY = float(os.environ.get("BLINKA_MCP2221_RESET_DELAY", 0.5))
 
 # from the C driver
 # http://ww1.microchip.com/downloads/en/DeviceDoc/mcp2221_0_1.tar.gz
 # others (???) determined during driver developement
-# pylint: disable=bad-whitespace
 RESP_ERR_NOERR = 0x00
 RESP_ADDR_NACK = 0x25
 RESP_READ_ERR = 0x7F
@@ -35,7 +34,6 @@ RESP_I2C_WRITINGNOSTOP = 0x45  # ???
 MCP2221_RETRY_MAX = 50
 MCP2221_MAX_I2C_DATA_LEN = 60
 MASK_ADDR_NACK = 0x40
-# pylint: enable=bad-whitespace
 
 
 class MCP2221:
@@ -53,7 +51,8 @@ class MCP2221:
     def __init__(self):
         self._hid = hid.device()
         self._hid.open(MCP2221.VID, MCP2221.PID)
-        self._reset()
+        if MCP2221_RESET_DELAY >= 0:
+            self._reset()
         self._gp_config = [0x07] * 4  # "don't care" initial value
         for pin in range(4):
             self.gp_set_mode(pin, self.GP_GPIO)  # set to GPIO mode
@@ -286,6 +285,8 @@ class MCP2221:
                     continue
                 if resp[2] in (RESP_READ_COMPL, RESP_READ_PARTIAL):
                     break
+            else:
+                raise RuntimeError("I2C read error: max retries reached.")
 
             # move data into buffer
             chunk = min(end - start, 60)
@@ -295,7 +296,7 @@ class MCP2221:
 
     # pylint: enable=too-many-arguments
 
-    def i2c_configure(self, baudrate=100000):
+    def _i2c_configure(self, baudrate=100000):
         """Configure I2C"""
         self._hid_xfer(
             bytes(
diff --git a/src/adafruit_blinka/microcontroller/mt8167/__init__.py b/src/adafruit_blinka/microcontroller/mt8167/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/adafruit_blinka/microcontroller/mt8167/pin.py b/src/adafruit_blinka/microcontroller/mt8167/pin.py
new file mode 100644 (file)
index 0000000..ff5e0e5
--- /dev/null
@@ -0,0 +1,64 @@
+"""MediaTek MT8167 pin names"""
+from adafruit_blinka.microcontroller.generic_linux.libgpiod_pin import Pin
+
+# All pins
+GPIO52 = Pin(52)  # SDA1      (pin 3)
+GPIO53 = Pin(53)  # SCL1      (pin 5)
+GPIO22 = Pin(22)  # EINT22    (pin 7)
+GPIO63 = Pin(63)  # UTXD0     (pin 8)
+GPIO62 = Pin(62)  # URXD0     (pin 10)
+GPIO9 = Pin(9)  # EINT9     (pin 11)
+GPIO36 = Pin(36)  # MRG_CLK   (pin 12)
+GPIO10 = Pin(10)  # EINT10    (pin 13)
+GPIO11 = Pin(11)  # EINT11    (pin 15)
+GPIO0 = Pin(0)  # EINT0     (pin 16)
+GPIO1 = Pin(1)  # EINT1     (pin 18)
+GPIO4 = Pin(4)  # EINT4     (pin 19)
+GPIO3 = Pin(3)  # EINT3     (pin 21)
+GPIO7 = Pin(7)  # EINT7     (pin 22)
+GPIO6 = Pin(6)  # EINT6     (pin 23)
+GPIO5 = Pin(5)  # EINT5     (pin 24)
+GPIO8 = Pin(8)  # EINT8     (pin 26)
+GPIO60 = Pin(60)  # SDA2      (pin 27)
+GPIO61 = Pin(61)  # SCL2      (pin 28)
+GPIO65 = Pin(65)  # UTXD1     (pin 29)
+GPIO64 = Pin(64)  # URXD1     (pin 31)
+GPIO12 = Pin(12)  # EINT12    (pin 32)
+GPIO25 = Pin(25)  # EINT25    (pin 33)
+GPIO37 = Pin(37)  # MRG_SYNC  (pin 35)
+GPIO13 = Pin(13)  # EINT13    (pin 36)
+GPIO45 = Pin(45)  # JTCLK     (pin 37)
+GPIO38 = Pin(38)  # MRG_DI    (pin 38)
+GPIO39 = Pin(39)  # MRG_DO    (pin 40)
+
+# Aliases
+PWM_A = GPIO25  # EINT12  (pin 32)
+PWM_B = GPIO11  # EINT25  (pin 33)
+PWM_C = GPIO12  # EINT11  (pin 15)
+
+I2C1_SDA = GPIO52  # SDA1  (pin 3)
+I2C1_SCL = GPIO53  # SCL1  (pin 5)
+
+I2C2_SDA = GPIO60  # SDA2  (pin 27)
+I2C2_SCL = GPIO61  # SCL2  (pin 28)
+
+SPI_MO = GPIO4  # EINT4  (pin 19)
+SPI_MI = GPIO3  # EINT3  (pin 21)
+SPI_CLK = GPIO6  # EINT6  (pin 23)
+SPI_CSB = GPIO5  # EINT5  (pin 24)
+
+# SysFS pwm outputs, pwm channel and pin in first tuple
+pwmOuts = (
+    ((0, 0), PWM_A),
+    ((0, 1), PWM_B),
+    ((0, 2), PWM_C),
+)
+
+# ordered as i2cId, sclId, sdaId
+i2cPorts = (
+    (3, I2C1_SCL, I2C1_SDA),
+    (0, I2C2_SCL, I2C2_SDA),
+)
+
+# ordered as spiId, sckId, mosiId, misoId
+spiPorts = ((0, SPI_CLK, SPI_MO, SPI_MI),)
index bf4127b722f2605c6348da724b5f25106594b2c7..8ab7ce09e52ec6c9a2d0e6d7772dc84aef511be7 100644 (file)
@@ -23,9 +23,7 @@ class Connection:
         from binhoHostAdapter import binhoUtilities
 
         # pylint: enable=import-outside-toplevel
-
-        utilities = binhoUtilities.binhoUtilities()
-        devices = utilities.listAvailableDevices()
+        devices = binhoUtilities.listAvailableDevices()
 
         if len(devices) > 0:
             Connection.__instance = binhoHostAdapter.binhoHostAdapter(devices[0])
index 75306f8270fe7db68da1f458c400cb904e2d9d3f..17731fb837e4bb371eb3afa9231498e75fc5b45c 100644 (file)
@@ -6,6 +6,8 @@ from adafruit_blinka.microcontroller.nova import Connection
 class I2C:
     """Custom I2C Class for Binho Nova"""
 
+    WHR_PAYLOAD_MAX_LENGTH = 1024
+
     def __init__(self, *, frequency=400000):
         self._nova = Connection.getInstance()
         self._nova.setNumericalBase(10)
@@ -13,6 +15,16 @@ class I2C:
         self._nova.setPullUpStateI2C(0, "EN")
         self._nova.setClockI2C(0, frequency)
 
+        self._novaCMDVer = "0"
+        if hasattr(self._nova, "getCommandVer"):
+            response = self._nova.getCommandVer().split(" ")
+            if response[0] != "-NG":
+                self._novaCMDVer = response[1]
+
+    def __del__(self):
+        """Close Nova on delete"""
+        self._nova.close()
+
     def scan(self):
         """Perform an I2C Device Scan"""
         scanResults = []
@@ -30,22 +42,39 @@ class I2C:
     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)
+        readBytes = 0
+        if int(self._novaCMDVer) >= 1:
+            chunks, rest = divmod(end - start, self.WHR_PAYLOAD_MAX_LENGTH)
+            for i in range(chunks):
+                chunk_start = start + i * self.WHR_PAYLOAD_MAX_LENGTH
+                chunk_end = chunk_start + self.WHR_PAYLOAD_MAX_LENGTH
+                self._nova.writeToReadFromI2C(
+                    0,
+                    address << 1,
+                    stop,
+                    readBytes,
+                    chunk_end - chunk_start,
+                    buffer[chunk_start:chunk_end],
+                )
+            if rest:
+                self._nova.writeToReadFromI2C(
+                    0, address << 1, stop, readBytes, rest, buffer[-1 * rest :]
+                )
+        else:
+            self._nova.startI2C(0, address << 1)
 
-        self._nova.startI2C(0, address << 1)
-
-        for i in range(start, end):
-            self._nova.writeByteI2C(0, buffer[i])
+            for i in range(start, end):
+                self._nova.writeByteI2C(0, buffer[i])
 
-        if stop:
-            self._nova.endI2C(0)
-        else:
-            self._nova.endI2C(0, True)
+            if stop:
+                self._nova.endI2C(0)
+            else:
+                self._nova.endI2C(0, True)
 
     # pylint: disable=unused-argument
     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]))
 
         if result != "-NG":
@@ -58,6 +87,7 @@ class I2C:
                 "Received error response from Binho Nova, result = " + result
             )
 
+    # pylint: disable=too-many-locals,too-many-branches
     def writeto_then_readfrom(
         self,
         address,
@@ -75,27 +105,75 @@ class I2C:
         """
         out_end = out_end if out_end else len(buffer_out)
         in_end = in_end if in_end else len(buffer_in)
+        if int(self._novaCMDVer) >= 1:
+            totalIn = in_end - in_start
+            totalOut = out_end - out_start
+            totalBytes = totalIn
+            if totalOut > totalIn:
+                totalBytes = totalOut
+            chunks, rest = divmod(totalBytes, self.WHR_PAYLOAD_MAX_LENGTH)
+            if rest > 0:
+                chunks += 1
+
+            for i in range(chunks):
+                # calculate the number of bytes to be written and read
+                numInBytes = self.WHR_PAYLOAD_MAX_LENGTH
+                if totalIn < self.WHR_PAYLOAD_MAX_LENGTH:
+                    numInBytes = totalIn
+                numOutBytes = self.WHR_PAYLOAD_MAX_LENGTH
+                if totalOut < self.WHR_PAYLOAD_MAX_LENGTH:
+                    numOutBytes = totalOut
+
+                # setup the buffer out chunk offset
+                buffer = "0"
+                if numOutBytes > 0:
+                    chunk_start = out_start + i * self.WHR_PAYLOAD_MAX_LENGTH
+                    chunk_end = chunk_start + numOutBytes
+                    buffer = buffer_out[chunk_start:chunk_end]
+
+                result = self._nova.writeToReadFromI2C(
+                    0, address << 1, stop, numInBytes, numOutBytes, buffer
+                )
+                totalIn -= numInBytes
+                totalOut -= numOutBytes
+
+                if result != "-NG":
+                    if numInBytes:
+                        resp = result.split(" ")
+                        resp = resp[2]
+
+                        for j in range(numInBytes):
+                            buffer_in[
+                                in_start + i * self.WHR_PAYLOAD_MAX_LENGTH + j
+                            ] = int(resp[j * 2] + resp[j * 2 + 1], 16)
+                else:
+                    raise RuntimeError(
+                        "Received error response from Binho Nova, result = " + result
+                    )
+        else:
+            self._nova.startI2C(0, address << 1)
 
-        self._nova.startI2C(0, address << 1)
-
-        for i in range(out_start, out_end):
-            self._nova.writeByteI2C(0, buffer_out[i])
+            for i in range(out_start, out_end):
+                self._nova.writeByteI2C(0, buffer_out[i])
 
-        self._nova.endI2C(0, True)
+            if stop:
+                self._nova.endI2C(0)
+            else:
+                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(" ")
+            if result != "-NG":
+                resp = result.split(" ")
 
-            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
-            )
+                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
+                )
 
 
-# pylint: enable=unused-argument
+# pylint: enable=unused-argument,too-many-locals,too-many-branches
index 00beba767064bb64a7c4d8289894aa1e6a02a532..2ff0c2594e909c7af5c0e27b21ee90e3e0baf5ed 100644 (file)
@@ -3,7 +3,7 @@
 try:
     from microcontroller.pin import pwmOuts
 except ImportError:
-    raise RuntimeError("No PWM outputs defined for this board")
+    raise RuntimeError("No PWM outputs defined for this board") from ImportError
 
 from microcontroller.pin import Pin
 
@@ -60,6 +60,7 @@ class PWMOut:
 
     def __del__(self):
         self.deinit()
+        PWMOut._nova.close()
 
     def __enter__(self):
         return self
index ce61fd631d48f5594830052ce8f0b828c7bcb44b..e03853dfc217af8061f1efadddfa7b1b2faa1f85 100644 (file)
@@ -6,7 +6,8 @@ class SPI:
     """Custom SPI Class for Binho Nova"""
 
     MSB = 0
-    PAYLOAD_MAX_LENGTH = 64
+    BUFFER_PAYLOAD_MAX_LENGTH = 64
+    WHR_PAYLOAD_MAX_LENGTH = 1024
 
     def __init__(self, clock):
         self._nova = Connection.getInstance()
@@ -17,6 +18,11 @@ class SPI:
         self._nova.setIOpinMode(0, "DOUT")
         self._nova.setIOpinMode(1, "DOUT")
         self._nova.beginSPI(0)
+        self._novaCMDVer = "0"
+        if hasattr(self._nova, "getCommandVer"):
+            response = self._nova.getCommandVer().split(" ")
+            if response[0] != "-NG":
+                self._novaCMDVer = response[1]
 
         # Cpol and Cpha set by mode
         # Mode  Cpol Cpha
@@ -25,10 +31,14 @@ class SPI:
         #  2     1    0
         #  3     1    1
 
+    def __del__(self):
+        """Close Nova on delete"""
+        self._nova.close()
+
     # pylint: disable=too-many-arguments,unused-argument
     def init(
         self,
-        baudrate=100000,
+        baudrate=1000000,
         polarity=0,
         phase=0,
         bits=8,
@@ -38,8 +48,6 @@ class SPI:
         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))
 
@@ -58,29 +66,80 @@ class SPI:
     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)
+        payloadMaxLength = self.BUFFER_PAYLOAD_MAX_LENGTH
+        if int(self._novaCMDVer) >= 1:
+            payloadMaxLength = self.WHR_PAYLOAD_MAX_LENGTH
+        chunks, rest = divmod(end - start, payloadMaxLength)
+
         for i in range(chunks):
-            chunk_start = start + i * self.PAYLOAD_MAX_LENGTH
-            chunk_end = chunk_start + self.PAYLOAD_MAX_LENGTH
-            buffer_data = buf[chunk_start:chunk_end]
-            self._nova.clearBuffer(0)
-            self._nova.writeToBuffer(0, 0, buffer_data)
-            self._nova.transferBufferSPI(0, chunk_end - chunk_start + 1)
+            chunk_start = start + i * payloadMaxLength
+            chunk_end = chunk_start + payloadMaxLength
+            if int(self._novaCMDVer) >= 1:
+                self._nova.writeToReadFromSPI(
+                    0, True, False, chunk_end - chunk_start, buf[chunk_start:chunk_end]
+                )
+            else:
+                self._nova.clearBuffer(0)
+                self._nova.writeToBuffer(0, 0, buf[chunk_start:chunk_end])
+                self._nova.transferBufferSPI(0, chunk_end - chunk_start + 1)
         if rest:
-            buffer_data = buf[-1 * rest :]
-            self._nova.clearBuffer(0)
-            self._nova.writeToBuffer(0, 0, buffer_data)
-            self._nova.transferBufferSPI(0, rest)
+            if int(self._novaCMDVer) >= 1:
+                self._nova.writeToReadFromSPI(0, True, False, rest, buf[-1 * rest :])
+            else:
+                self._nova.clearBuffer(0)
+                self._nova.writeToBuffer(0, 0, buf[-1 * rest :])
+                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))
-            )
+        if int(self._novaCMDVer) >= 1:
+            chunks, rest = divmod(end - start, self.WHR_PAYLOAD_MAX_LENGTH)
+            i = 0
+            for i in range(chunks):
+                chunk_start = start + i * self.WHR_PAYLOAD_MAX_LENGTH
+                chunk_end = chunk_start + self.WHR_PAYLOAD_MAX_LENGTH
+                result = self._nova.writeToReadFromSPI(
+                    0, False, True, chunk_end - chunk_start, write_value
+                )
+                if result != "-NG":
+                    resp = result.split(" ")
+                    resp = resp[2]
+                    # loop over half of resp len as we're reading 2 chars at a time to form a byte
+                    loops = int(len(resp) / 2)
+                    for j in range(loops):
+                        buf[(i * self.WHR_PAYLOAD_MAX_LENGTH) + start + j] = int(
+                            resp[j * 2] + resp[j * 2 + 1], 16
+                        )
+                else:
+                    raise RuntimeError(
+                        "Received error response from Binho Nova, result = " + result
+                    )
+            if rest:
+                result = self._nova.writeToReadFromSPI(
+                    0, False, True, rest, write_value
+                )
+                if result != "-NG":
+                    resp = result.split(" ")
+                    resp = resp[2]
 
-    # pylint: disable=too-many-arguments
+                    # loop over half of resp len as we're reading 2 chars at a time to form a byte
+                    loops = int(len(resp) / 2)
+                    for j in range(loops):
+                        buf[(i * self.WHR_PAYLOAD_MAX_LENGTH) + start + j] = int(
+                            resp[j * 2] + resp[j * 2 + 1], 16
+                        )
+                else:
+                    raise RuntimeError(
+                        "Received error response from Binho Nova, result = " + result
+                    )
+        else:
+            for i in range(start, end):
+                buf[start + i] = int(
+                    self.get_received_data(self._nova.transferSPI(0, write_value))
+                )
+
+    # pylint: disable=too-many-arguments,too-many-locals,too-many-branches
     def write_readinto(
         self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
     ):
@@ -96,11 +155,61 @@ class SPI:
             tmp = bytearray(buffer_out)
             tmp.extend([0] * (readlen - len(buffer_out)))
             buffer_out = tmp
-        i = 0
-        for data_out in buffer_out:
-            data_in = int(self.get_received_data(self._nova.transferSPI(0, data_out)))
-            if i < readlen:
-                buffer_in[in_start + i] = data_in
-            i += 1
-
-    # pylint: enable=too-many-arguments
+
+        if int(self._novaCMDVer) >= 1:
+            chunks, rest = divmod(len(buffer_out), self.WHR_PAYLOAD_MAX_LENGTH)
+            i = 0
+            for i in range(chunks):
+                chunk_start = out_start + i * self.WHR_PAYLOAD_MAX_LENGTH
+                chunk_end = chunk_start + self.WHR_PAYLOAD_MAX_LENGTH
+                result = self._nova.writeToReadFromSPI(
+                    0,
+                    True,
+                    True,
+                    chunk_end - chunk_start,
+                    buffer_out[chunk_start:chunk_end],
+                )
+
+                if result != "-NG":
+                    resp = result.split(" ")
+                    resp = resp[2]
+
+                    # loop over half of resp len as we're reading 2 chars at a time to form a byte
+                    loops = int(len(resp) / 2)
+                    for j in range(loops):
+                        buffer_in[
+                            (i * self.WHR_PAYLOAD_MAX_LENGTH) + in_start + j
+                        ] = int(resp[j * 2] + resp[j * 2 + 1], 16)
+                else:
+                    raise RuntimeError(
+                        "Received error response from Binho Nova, result = " + result
+                    )
+            if rest:
+                result = self._nova.writeToReadFromSPI(
+                    0, True, True, rest, buffer_out[-1 * rest :]
+                )
+                if result != "-NG":
+                    resp = result.split(" ")
+                    resp = resp[2]
+
+                    # loop over half of resp len as we're reading 2 chars at a time to form a byte
+                    loops = int(len(resp) / 2)
+                    for j in range(loops):
+                        buffer_in[
+                            (i * self.WHR_PAYLOAD_MAX_LENGTH) + in_start + j
+                        ] = int(resp[j * 2] + resp[j * 2 + 1], 16)
+                else:
+                    raise RuntimeError(
+                        "Received error response from Binho Nova, result = " + result
+                    )
+            print(buffer_in)
+        else:
+            for data_out in buffer_out:
+                data_in = int(
+                    self.get_received_data(self._nova.transferSPI(0, data_out))
+                )
+                if i < readlen:
+                    buffer_in[in_start + i] = data_in
+                i += 1
+
+    # pylint: enable=too-many-arguments,too-many-locals,too-many-branches
index d84a339178f455eb1364b513e962b7062379982a..5d698f8eabc4b06a7a933abe9f8781422b351627 100644 (file)
@@ -43,6 +43,10 @@ class UART:
         self._nova.beginBridgeUART(self._id)
 
     # pylint: enable=too-many-arguments,unused-argument
+    def __del__(self):
+        """Close Nova on delete"""
+        self.deinit()
+        self._nova.close()
 
     def deinit(self):
         """Deinitialize"""
diff --git a/src/adafruit_blinka/microcontroller/nxp_imx6ull/__init__.py b/src/adafruit_blinka/microcontroller/nxp_imx6ull/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/adafruit_blinka/microcontroller/nxp_imx6ull/pin.py b/src/adafruit_blinka/microcontroller/nxp_imx6ull/pin.py
new file mode 100644 (file)
index 0000000..7ffa331
--- /dev/null
@@ -0,0 +1,67 @@
+"""NXP IMX6ULL pin names"""
+from adafruit_blinka.microcontroller.generic_linux.libgpiod_pin import Pin
+
+# GPIO num = reconment function = Pin((chip, line))
+GPIO31 = I2C2_SDA = Pin((0, 31))  # GPIO1_IO31
+GPIO30 = I2C2_SCL = Pin((0, 30))  # GPIO1_IO30
+
+GPIO29 = I2C3_SDA = Pin((0, 29))  # GPIO1_IO29
+GPIO28 = I2C3_SCL = Pin((0, 28))  # GPIO1_IO28
+
+GPIO24 = UART3_TXD = Pin((0, 24))  # GPIO1_IO24
+GPIO25 = UART3_RXD = Pin((0, 25))  # GPIO1_IO25
+
+GPIO22 = ECSPI3_MOSI = Pin((0, 22))  # GPIO1_IO22
+GPIO23 = ECSPI3_MISO = Pin((0, 23))  # GPIO1_IO23
+GPIO21 = ECSPI3_SCLK = Pin((0, 21))  # GPIO1_IO21
+GPIO20 = ECSPI3_SS0 = Pin((0, 20))  # GPIO1_IO20
+GPIO18 = ECSPI3_SS1 = Pin((0, 18))  # GPIO1_IO18
+
+GPIO0 = ADC_IN0 = Pin((0, 0))  # GPIO1_IO0
+GPIO1 = ADC_IN1 = Pin((0, 1))  # GPIO1_IO2
+GPIO2 = ADC_IN2 = Pin((0, 2))  # GPIO1_IO2
+GPIO3 = ADC_IN3 = Pin((0, 3))  # GPIO1_IO3
+GPIO4 = PWM_C3 = Pin((0, 4))  # GPIO1_IO4
+GPIO26 = Pin((0, 26))  # GPIO1_IO26
+GPIO27 = Pin((0, 27))  # GPIO1_IO27
+
+GPIO113 = Pin((3, 17))  # GPIO4_IO17
+GPIO114 = Pin((3, 18))  # GPIO4_IO18
+GPIO115 = PWM_C7 = Pin((3, 19))  # GPIO4_IO19
+GPIO116 = PWM_C8 = Pin((3, 20))  # GPIO4_IO20
+GPIO117 = Pin((3, 21))  # GPIO4_IO21
+GPIO118 = Pin((3, 22))  # GPIO4_IO22
+GPIO119 = Pin((3, 23))  # GPIO4_IO23
+GPIO120 = Pin((3, 24))  # GPIO4_IO24
+GPIO121 = Pin((3, 25))  # GPIO4_IO25
+GPIO112 = Pin((3, 26))  # GPIO4_IO26
+GPIO123 = Pin((3, 27))  # GPIO4_IO27
+GPIO124 = Pin((3, 28))  # GPIO4_IO28
+
+GPIO129 = Pin((4, 1))  # GPIO5_IO1
+
+i2cPorts = (
+    (1, I2C2_SCL, I2C2_SDA),
+    (2, I2C3_SCL, I2C3_SDA),
+)
+
+# ordered as spiId, sckId, mosiId, misoId
+spiPorts = ((2, ECSPI3_SCLK, ECSPI3_MOSI, ECSPI3_MISO),)
+
+# UART3_TXD/RXD on /dev/ttymxc2
+uartPorts = ((2, UART3_TXD, UART3_RXD),)
+
+# SysFS pwm outputs, pwm channel and pin in first tuple
+pwmOuts = (
+    ((2, 0), PWM_C3),
+    ((6, 0), PWM_C7),
+    ((7, 0), PWM_C8),
+)
+
+# SysFS analog inputs, Ordered as analog analogInId, device, and channel
+analogIns = (
+    (ADC_IN0, 0, 0),
+    (ADC_IN1, 0, 1),
+    (ADC_IN2, 0, 2),
+    (ADC_IN3, 0, 3),
+)
index cfa96fe2ccababefb07f1e701a95a584d1842573..24d542dd5770a3a8d11b67f106fbd8f9822b35f3 100644 (file)
@@ -4,11 +4,11 @@ try:
     from greatfet.interfaces.adc import ADC
 
     gf = GreatFET()
-except:
+except ModuleNotFoundError:
     raise RuntimeError(
         "Unable to create GreatFET object. Make sure library is "
         "installed and the device is connected."
-    )
+    ) from ModuleNotFoundError
 
 
 class Pin:
index 5bb7889d3430f74aff8f13a37f2a6f6da742898d..91c3ede1b12e8902d2c3cc2a8ac3523d1d6b278c 100644 (file)
@@ -5,7 +5,7 @@ from greatfet import GreatFET
 try:
     from microcontroller.pin import pwmOuts
 except ImportError:
-    raise RuntimeError("No PWM outputs defined for this board")
+    raise RuntimeError("No PWM outputs defined for this board") from ImportError
 
 # pylint: disable=unnecessary-pass
 class PWMError(IOError):
index 17859a42d374e19b23f93de123c7ea97172072d7..28b4fd2a921a445af5789e7312e19d404f94614e 100644 (file)
@@ -93,7 +93,7 @@ class SPI:
     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._transmit([], end - start)
+        result = self._transmit([write_value] * (end - start), end - start)
         for i, b in enumerate(result):
             buf[start + i] = b
 
diff --git a/src/adafruit_blinka/microcontroller/pentium/__init__.py b/src/adafruit_blinka/microcontroller/pentium/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/adafruit_blinka/microcontroller/pentium/n3710/.gitignore b/src/adafruit_blinka/microcontroller/pentium/n3710/.gitignore
new file mode 100644 (file)
index 0000000..0e7f550
--- /dev/null
@@ -0,0 +1 @@
+pins
diff --git a/src/adafruit_blinka/microcontroller/pentium/n3710/__init__.py b/src/adafruit_blinka/microcontroller/pentium/n3710/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/adafruit_blinka/microcontroller/pentium/n3710/pin.py b/src/adafruit_blinka/microcontroller/pentium/n3710/pin.py
new file mode 100644 (file)
index 0000000..3093a20
--- /dev/null
@@ -0,0 +1,86 @@
+"""Pentium N3710 (Braswell core SOC) pin names
+   i2c and GPIO can be accessed through Blinka.
+   For i2c use IC20_SCL, IC20-SDA and IC21-SCL, IC21-SDA in the i2c(<sdl, sda>) calls.
+   For UART use pyserial"""
+from adafruit_blinka.microcontroller.generic_linux.libgpiod_pin import Pin
+
+# gpiochip3
+GPIO_243 = Pin((3, 15))
+GPIO_246 = Pin((3, 18))
+GPIO_247 = Pin((3, 19))
+GPIO_249 = Pin((3, 21))
+GPIO_250 = Pin((3, 22))
+GPIO_253 = Pin((3, 25))
+GPIO_273 = Pin((3, 45))
+GPIO_275 = Pin((3, 47))
+GPIO_276 = Pin((3, 48))
+GPIO_278 = Pin((3, 50))
+GPIO_279 = Pin((3, 51))
+GPIO_280 = Pin((3, 52))
+GPIO_307 = Pin((3, 79))
+
+SDIO_D3 = SDMMC2_D3 = GPIO_243
+SDIO_DI = SDMMC2_D1 = GPIO_246
+SDIO_CLK = SDMMC2_CLK = GPIO_247
+SDIO_D2 = SDMMC2_D2 = GPIO_249
+SDIO_CMD = SDMMC2_CMD = GPIO_250
+SDIO_D0 = SDMMC2_D0 = GPIO_253
+
+MF_LPC_AD2 = GPIO_273
+MF_LPC_AD0 = GPIO_275
+LPC_FRAMEB = GPIO_276
+MF_LPC_AD3 = GPIO_278
+MF_LPC_CLKOUT0 = GPIO_279
+MF_LPC_AD1 = GPIO_280
+ILB_SERIRQ = GPIO_307
+
+# ggpiochip1
+GPIO_358 = Pin((1, 17))
+GPIO_SUS3 = SDIO_WAKE = GPIO_358
+
+
+# gpiochip0
+GPIO_490 = Pin((0, 76))
+GPIO_492 = Pin((0, 78))
+
+SATA_GP1 = TS_INT = GPIO_490
+SATA_GP2 = TS_RST = GPIO_492
+
+
+# not general gpio on chip 0
+# use pyserial not blinka.  These are only included for completeness
+
+UART1_RXD = Pin((0, 16))
+UART1_TXD = Pin((0, 20))
+UART1_RTS = Pin((0, 15))
+UART1_CTS = Pin((0, 18))
+
+UART2_RXD = Pin((0, 17))
+UART2_TXD = Pin((0, 21))
+UART2_RTS = Pin((0, 19))
+UART2_CTS = Pin((0, 22))
+
+GPIO_429 = UART1_RTS
+GPIO_430 = UART1_RXD
+GPIO_431 = UART2_RXD
+GPIO_432 = UART1_CTS
+GPIO_434 = UART1_TXD
+GPIO_435 = UART2_TXD
+GPIO_436 = UART2_CTS
+
+# i2c use these addresses when accessing i2c from Blinka.  You can also access
+# the i2c useing smbus
+I2C0_SDA = Pin((0, 61))  # IC21 on diagram, port 0 in hardware manual
+I2C0_SCL = Pin((0, 65))
+
+I2C1_SDA = TS_I2C_SDA = Pin((0, 45))  # I2C2 on diagram, port 5 in hardware manual
+I2C1_SCL = TS_I2C_SCL = Pin((0, 48))
+
+
+GPIO_469 = I2C1_SDA  # I2C2 on diagram
+GPIO_472 = I2C1_SCL
+GPIO_475 = I2C0_SDA  # I2C1 on diagram
+GPIO_479 = I2C0_SCL
+
+# ordered as i2cId, sclId, sdaId
+i2cPorts = ((0, I2C0_SCL, I2C0_SDA), (1, I2C1_SCL, I2C1_SDA))
diff --git a/src/adafruit_blinka/microcontroller/rockchip/PWMOut.py b/src/adafruit_blinka/microcontroller/rockchip/PWMOut.py
new file mode 100644 (file)
index 0000000..09c4a8e
--- /dev/null
@@ -0,0 +1,392 @@
+"""
+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
+from time import sleep
+from errno import EACCES
+
+try:
+    from microcontroller.pin import pwmOuts
+except ImportError:
+    raise RuntimeError("No PWM outputs defined for this board.") from ImportError
+
+
+# pylint: disable=unnecessary-pass, too-many-instance-attributes
+
+
+class PWMError(IOError):
+    """Base class for PWM errors."""
+
+    pass
+
+
+# pylint: enable=unnecessary-pass
+
+
+class PWMOut:
+    """Pulse Width Modulation Output Class"""
+
+    # Number of retries to check for successful PWM export on open
+    PWM_STAT_RETRIES = 10
+    # Delay between check for successful PWM export on open (100ms)
+    PWM_STAT_DELAY = 0.1
+
+    # Sysfs paths
+    _chip_path = "pwmchip{}"
+    _channel_path = "pwm{}"
+
+    def __init__(self, pwm, *, frequency=500, duty_cycle=0, variable_frequency=False):
+        """Instantiate a PWM object and open the sysfs PWM corresponding to the
+        specified chip and channel.
+        Args:
+            pwm (str): PWM pin.
+            frequency (int, float): target frequency in Hertz (32-bit).
+            duty_cycle (int, float): The fraction of each pulse which is high (16-bit).
+            variable_frequency (bool): True if the frequency will change over time.
+        Returns:
+            PWM: PWM object.
+        Raises:
+            PWMError: if an I/O or OS error occurs.
+            TypeError: if `chip` or `channel` types are invalid.
+            LookupError: if PWM chip does not exist.
+            TimeoutError: if waiting for PWM export times out.
+        """
+
+        self._chip = None
+        self._channel = None
+        self._period_ns = 0
+        self._open(pwm, frequency, duty_cycle, variable_frequency)
+
+    def __del__(self):
+        self.close()
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        self.close()
+
+    def _open(self, pwm, frequency, duty_cycle, variable_frequency):
+        for pwmout in pwmOuts:
+            if pwmout[1] == pwm:
+                self._chip = pwmout[0][0]
+                self._channel = pwmout[0][1]
+
+        self._chip_path = os.path.join(
+            "/sys/class/pwm", self._chip_path.format(self._chip)
+        )
+        self._channel_path = os.path.join(
+            self._chip_path, self._channel_path.format(self._channel)
+        )
+
+        if variable_frequency:
+            print("Variable Frequency is not supported, continuing without it...")
+
+        if not os.path.isdir(self._chip_path):
+            raise LookupError("Opening PWM: PWM chip {} not found.".format(self._chip))
+
+        if not os.path.isdir(self._channel_path):
+            # Exporting the PWM.
+            try:
+                with open(os.path.join(self._chip_path, "export"), "w") as f_export:
+                    f_export.write("{:d}\n".format(self._channel))
+            except IOError as e:
+                raise PWMError(
+                    e.errno, "Exporting PWM channel: " + e.strerror
+                ) from IOError
+
+            # Loop until PWM is exported
+            exported = False
+            for i in range(PWMOut.PWM_STAT_RETRIES):
+                if os.path.isdir(self._channel_path):
+                    exported = True
+                    break
+
+                sleep(PWMOut.PWM_STAT_DELAY)
+
+            if not exported:
+                raise TimeoutError(
+                    'Exporting PWM: waiting for "{:s}" timed out.'.format(
+                        self._channel_path
+                    )
+                )
+
+            # Loop until 'period' is writable, This could take some time after
+            # export as application of the udev rules after export is asynchronous.
+            # Without this loop, the following properties may not be writable yet.
+            for i in range(PWMOut.PWM_STAT_RETRIES):
+                try:
+                    with open(
+                        os.path.join(self._channel_path, "period"),
+                        "w",
+                    ):
+                        break
+                except IOError as e:
+                    if e.errno != EACCES or (
+                        e.errno == EACCES and i == PWMOut.PWM_STAT_RETRIES - 1
+                    ):
+                        raise PWMError(
+                            e.errno, "Opening PWM period: " + e.strerror
+                        ) from IOError
+
+                sleep(PWMOut.PWM_STAT_DELAY)
+
+            self.frequency = frequency
+            self.duty_cycle = duty_cycle
+
+            # Cache the period for fast duty cycle updates
+            self._period_ns = self._get_period_ns()
+
+    def close(self):
+        """Close the PWM."""
+        if self._channel is not None:
+            # Unexporting the PWM channel
+            try:
+                unexport_fd = os.open(
+                    os.path.join(self._chip_path, "unexport"), os.O_WRONLY
+                )
+                os.write(unexport_fd, "{:d}\n".format(self._channel).encode())
+                os.close(unexport_fd)
+            except OSError as e:
+                raise PWMError(e.errno, "Unexporting PWM: " + e.strerror) from OSError
+
+        self._chip = None
+        self._channel = None
+
+    def _write_channel_attr(self, attr, value):
+        with open(os.path.join(self._channel_path, attr), "w") as f_attr:
+            f_attr.write(value + "\n")
+
+    def _read_channel_attr(self, attr):
+        with open(os.path.join(self._channel_path, attr), "r") as f_attr:
+            return f_attr.read().strip()
+
+    # Methods
+
+    def enable(self):
+        """Enable the PWM output."""
+        self.enabled = True
+
+    def disable(self):
+        """Disable the PWM output."""
+        self.enabled = False
+
+    # Mutable properties
+
+    def _get_period(self):
+        return float(self.period_ms) / 1000
+
+    def _set_period(self, period):
+        if not isinstance(period, (int, float)):
+            raise TypeError("Invalid period type, should be int.")
+
+        self.period_ms = int(period * 1000)
+
+    period = property(_get_period, _set_period)
+    """Get or set the PWM's output period in seconds.
+
+    Raises:
+        PWMError: if an I/O or OS error occurs.
+        TypeError: if value type is not int.
+
+    :type: int, float
+    """
+
+    def _get_period_ms(self):
+        return self.period_us / 1000
+
+    def _set_period_ms(self, period_ms):
+        if not isinstance(period_ms, (int, float)):
+            raise TypeError("Invalid period type, should be int or float.")
+        self.period_us = int(period_ms * 1000)
+
+    period_ms = property(_get_period_ms, _set_period_ms)
+    """Get or set the PWM's output period in milliseconds.
+
+    Raises:
+        PWMError: if an I/O or OS error occurs.
+        TypeError: if value type is not int.
+
+    :type: int, float
+    """
+
+    def _get_period_us(self):
+        return self.period_ns / 1000
+
+    def _set_period_us(self, period_us):
+        if not isinstance(period_us, int):
+            raise TypeError("Invalid period type, should be int.")
+
+        self.period_ns = int(period_us * 1000)
+
+    period_us = property(_get_period_us, _set_period_us)
+    """Get or set the PWM's output period in microseconds.
+
+    Raises:
+        PWMError: if an I/O or OS error occurs.
+        TypeError: if value type is not int.
+
+    :type: int
+    """
+
+    def _get_period_ns(self):
+        period_ns = self._read_channel_attr("period")
+        try:
+            period_ns = int(period_ns)
+        except ValueError:
+            raise PWMError(
+                None, 'Unknown period value: "%s".' % period_ns
+            ) from ValueError
+
+        self._period_ns = period_ns
+
+        return period_ns
+
+    def _set_period_ns(self, period_ns):
+        if not isinstance(period_ns, int):
+            raise TypeError("Invalid period type, should be int.")
+
+        self._write_channel_attr("period", str(period_ns))
+
+        # Update our cached period
+        self._period_ns = period_ns
+
+    period_ns = property(_get_period_ns, _set_period_ns)
+    """Get or set the PWM's output period in nanoseconds.
+
+    Raises:
+        PWMError: if an I/O or OS error occurs.
+        TypeError: if value type is not int.
+
+    :type: int
+    """
+
+    def _get_duty_cycle_ns(self):
+        duty_cycle_ns_str = self._read_channel_attr("duty_cycle")
+
+        try:
+            duty_cycle_ns = int(duty_cycle_ns_str)
+        except ValueError:
+            raise PWMError(
+                None, 'Unknown duty cycle value: "{:s}"'.format(duty_cycle_ns_str)
+            ) from ValueError
+
+        return duty_cycle_ns
+
+    def _set_duty_cycle_ns(self, duty_cycle_ns):
+        if not isinstance(duty_cycle_ns, int):
+            raise TypeError("Invalid duty cycle type, should be int.")
+
+        self._write_channel_attr("duty_cycle", str(duty_cycle_ns))
+
+    duty_cycle_ns = property(_get_duty_cycle_ns, _set_duty_cycle_ns)
+    """Get or set the PWM's output duty cycle in nanoseconds.
+
+    Raises:
+        PWMError: if an I/O or OS error occurs.
+        TypeError: if value type is not int.
+
+    :type: int
+    """
+
+    def _get_duty_cycle(self):
+        return float(self.duty_cycle_ns) / self._period_ns
+
+    def _set_duty_cycle(self, duty_cycle):
+        if not isinstance(duty_cycle, (int, float)):
+            raise TypeError("Invalid duty cycle type, should be int or float.")
+
+        if not 0.0 <= duty_cycle <= 1.0:
+            raise ValueError("Invalid duty cycle value, should be between 0.0 and 1.0.")
+
+        # Convert duty cycle from ratio to nanoseconds
+        self.duty_cycle_ns = int(duty_cycle * self._period_ns)
+
+    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.
+    Raises:
+        PWMError: if an I/O or OS error occurs.
+        TypeError: if value type is not int or float.
+        ValueError: if value is out of bounds of 0.0 to 1.0.
+    :type: int, float
+    """
+
+    def _get_frequency(self):
+        return 1.0 / self.period
+
+    def _set_frequency(self, frequency):
+        if not isinstance(frequency, (int, float)):
+            raise TypeError("Invalid frequency type, should be int or float.")
+
+        self.period = 1.0 / frequency
+
+    frequency = property(_get_frequency, _set_frequency)
+    """Get or set the PWM's output frequency in Hertz.
+    Raises:
+        PWMError: if an I/O or OS error occurs.
+        TypeError: if value type is not int or float.
+    :type: int, float
+    """
+
+    def _get_polarity(self):
+        return self._read_channel_attr("polarity")
+
+    def _set_polarity(self, polarity):
+        if not isinstance(polarity, str):
+            raise TypeError("Invalid polarity type, should be str.")
+
+        if polarity.lower() not in ["normal", "inversed"]:
+            raise ValueError('Invalid polarity, can be: "normal" or "inversed".')
+
+        self._write_channel_attr("polarity", polarity.lower())
+
+    polarity = property(_get_polarity, _set_polarity)
+    """Get or set the PWM's output polarity. Can be "normal" or "inversed".
+    Raises:
+        PWMError: if an I/O or OS error occurs.
+        TypeError: if value type is not str.
+        ValueError: if value is invalid.
+    :type: str
+    """
+
+    def _get_enabled(self):
+        enabled = self._read_channel_attr("enable")
+
+        if enabled == "1":
+            return True
+        if enabled == "0":
+            return False
+
+        raise PWMError(None, 'Unknown enabled value: "{:s}"'.format(enabled))
+
+    def _set_enabled(self, value):
+        if not isinstance(value, bool):
+            raise TypeError("Invalid enabled type, should be bool.")
+
+        self._write_channel_attr("enable", "1" if value else "0")
+
+    enabled = property(_get_enabled, _set_enabled)
+    """Get or set the PWM's output enabled state.
+    Raises:
+        PWMError: if an I/O or OS error occurs.
+        TypeError: if value type is not bool.
+    :type: bool
+    """
+
+    # String representation
+
+    def __str__(self):
+        return (
+            "PWM {:d}, chip {:d} (period={:f} sec, duty_cycle={:f}%,"
+            " polarity={:s}, enabled={:s})".format(
+                self._channel,
+                self._chip,
+                self.period,
+                self.duty_cycle * 100,
+                self.polarity,
+                str(self.enabled),
+            )
+        )
index 80c5c7682340697fe2934f52c5a3271578f4253f..818c9dd6c0dea99ac965c8135dfdcfeba4a3ff5a 100644 (file)
@@ -134,10 +134,12 @@ ADC_IN0 = 1
 
 
 # I2C
+I2C0_SDA = GPIO1_D0
+I2C0_SCL = GPIO1_D1
 I2C1_SDA = GPIO0_B3
 I2C1_SCL = GPIO0_B4
-I2C2_SDA = GPIO1_D0
-I2C2_SCL = GPIO1_D1
+I2C2_SDA = GPIO2_A2
+I2C2_SCL = GPIO2_A3
 I2C3_SDA = GPIO0_B7
 I2C3_SCL = GPIO0_C0
 
@@ -161,6 +163,7 @@ PWM3 = GPIO0_C0
 
 # ordered as i2cId, SCL, SDA
 i2cPorts = (
+    (0, I2C0_SCL, I2C0_SDA),
     (1, I2C1_SCL, I2C1_SDA),
     (2, I2C2_SCL, I2C2_SDA),
     (3, I2C3_SCL, I2C3_SDA),
diff --git a/src/adafruit_blinka/microcontroller/rockchip/rk3399/__init__.py b/src/adafruit_blinka/microcontroller/rockchip/rk3399/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/adafruit_blinka/microcontroller/rockchip/rk3399/pin.py b/src/adafruit_blinka/microcontroller/rockchip/rk3399/pin.py
new file mode 100644 (file)
index 0000000..4419861
--- /dev/null
@@ -0,0 +1,77 @@
+"""A Pin class for use with Rockchip RK3399."""
+
+from adafruit_blinka.microcontroller.generic_linux.sysfs_pin import Pin
+
+GPIO1_A7 = Pin(39)
+GPIO1_B0 = Pin(40)
+GPIO1_B1 = Pin(41)
+GPIO1_B2 = Pin(42)
+GPIO2_A0 = Pin(64)
+GPIO2_A1 = Pin(65)
+GPIO2_A7 = Pin(71)
+GPIO2_B0 = Pin(72)
+GPIO2_B1 = Pin(73)
+GPIO2_B2 = Pin(74)
+GPIO2_B3 = Pin(75)
+GPIO2_B4 = Pin(76)
+GPIO3_C0 = Pin(112)
+GPIO4_A3 = Pin(131)
+GPIO4_A4 = Pin(132)
+GPIO4_A5 = Pin(133)
+GPIO4_A6 = Pin(134)
+GPIO4_A7 = Pin(135)
+GPIO4_C2 = Pin(146)
+GPIO4_C3 = Pin(147)
+GPIO4_C4 = Pin(148)
+GPIO4_C5 = Pin(149)
+GPIO4_C6 = Pin(150)
+GPIO4_D2 = Pin(154)
+GPIO4_D4 = Pin(156)
+GPIO4_D5 = Pin(157)
+GPIO4_D6 = Pin(158)
+ADC_IN0 = 1
+
+# I2C
+I2C2_SDA = GPIO2_A0
+I2C2_SCL = GPIO2_A1
+I2C6_SDA = GPIO2_B1
+I2C6_SCL = GPIO2_B2
+I2C7_SDA = GPIO2_A7
+I2C7_SCL = GPIO2_B0
+
+# SPI
+SPI1_CS = GPIO1_B2
+SPI1_SCLK = GPIO1_B1
+SPI1_MISO = GPIO1_B0
+SPI1_MOSI = GPIO1_A7
+SPI2_CS = GPIO2_B4
+SPI2_SCLK = GPIO2_A1
+SPI2_MISO = GPIO2_B1
+SPI2_MOSI = GPIO2_B2
+
+# UART
+UART0_TX = GPIO4_C4
+UART0_RX = GPIO4_C3
+
+# PWM
+PWM0 = GPIO4_C2
+PWM1 = GPIO4_C6
+
+# ordered as i2cId, SCL, SDA
+i2cPorts = (
+    (0, I2C2_SCL, I2C2_SDA),
+    (1, I2C6_SCL, I2C6_SDA),
+    (7, I2C7_SCL, I2C7_SDA),
+)
+
+# ordered as spiId, sckId, mosiId, misoId
+spiPorts = ((1, SPI1_SCLK, SPI1_MOSI, SPI1_MISO),)
+
+# SysFS pwm outputs, pwm channel and pin in first tuple
+pwmOuts = (
+    ((0, 0), PWM0),
+    ((1, 0), PWM1),
+)
+
+# SysFS analog inputs, Ordered as analog analogInId, device, and channel
+analogIns = ((ADC_IN0, 0, 0),)
diff --git a/src/adafruit_blinka/microcontroller/stm32/stm32f405/__init__.py b/src/adafruit_blinka/microcontroller/stm32/stm32f405/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
similarity index 98%
rename from src/adafruit_blinka/microcontroller/stm32/pin.py
rename to src/adafruit_blinka/microcontroller/stm32/stm32f405/pin.py
index b308069c35cdd7c3603bb4d039cc7d2e65a2eba0..52ec1c0e68428dde44d40ae42e07b3bf0daf7377 100755 (executable)
@@ -1,4 +1,4 @@
-"""STM32 pins"""
+"""STM32F405 pins"""
 
 from microcontroller import Pin
 
diff --git a/src/adafruit_blinka/microcontroller/stm32/stm32mp157/__init__.py b/src/adafruit_blinka/microcontroller/stm32/stm32mp157/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/adafruit_blinka/microcontroller/stm32/stm32mp157/pin.py b/src/adafruit_blinka/microcontroller/stm32/stm32mp157/pin.py
new file mode 100755 (executable)
index 0000000..0196982
--- /dev/null
@@ -0,0 +1,154 @@
+"""STM32MP157 pins"""
+from adafruit_blinka.microcontroller.generic_linux.periphery_pin import Pin
+
+PA0 = Pin((0, 0))
+PA1 = Pin((0, 1))
+PA2 = Pin((0, 2))
+PA3 = Pin((0, 3))
+PA4 = Pin((0, 4))
+PA5 = Pin((0, 5))
+PA6 = Pin((0, 6))
+PA7 = Pin((0, 7))
+PA8 = Pin((0, 8))
+PA9 = Pin((0, 9))
+PA11 = Pin((0, 11))
+PA12 = Pin((0, 12))
+PA13 = Pin((0, 13))
+PA14 = Pin((0, 14))
+PA15 = Pin((0, 15))
+PB0 = Pin((1, 0))
+PB1 = Pin((1, 1))
+PB2 = Pin((1, 2))
+PB3 = Pin((1, 3))
+PB4 = Pin((1, 4))
+PB5 = Pin((1, 5))
+PB6 = Pin((1, 6))
+PB7 = Pin((1, 7))
+PB8 = Pin((1, 8))
+PB9 = Pin((1, 9))
+PB10 = Pin((1, 10))
+PB11 = Pin((1, 11))
+PB12 = Pin((1, 12))
+PB13 = Pin((1, 13))
+PB14 = Pin((1, 14))
+PB15 = Pin((1, 15))
+PC0 = Pin((2, 0))
+PC1 = Pin((2, 1))
+PC2 = Pin((2, 2))
+PC3 = Pin((2, 3))
+PC4 = Pin((2, 4))
+PC5 = Pin((2, 5))
+PC6 = Pin((2, 6))
+PC7 = Pin((2, 7))
+PC8 = Pin((2, 8))
+PC9 = Pin((2, 9))
+PC10 = Pin((2, 10))
+PC11 = Pin((2, 11))
+PC12 = Pin((2, 12))
+PC13 = Pin((2, 13))
+PD0 = Pin((3, 0))
+PD1 = Pin((3, 1))
+PD2 = Pin((3, 2))
+PD3 = Pin((3, 3))
+PD4 = Pin((3, 4))
+PD5 = Pin((3, 5))
+PD6 = Pin((3, 6))
+PD7 = Pin((3, 7))
+PD8 = Pin((3, 8))
+PD9 = Pin((3, 9))
+PD10 = Pin((3, 10))
+PD11 = Pin((3, 11))
+PD12 = Pin((3, 12))
+PD13 = Pin((3, 13))
+PD14 = Pin((3, 14))
+PD15 = Pin((3, 15))
+PE0 = Pin((4, 0))
+PE1 = Pin((4, 1))
+PE2 = Pin((4, 2))
+PE3 = Pin((4, 3))
+PE4 = Pin((4, 4))
+PE5 = Pin((4, 5))
+PE6 = Pin((4, 6))
+PE7 = Pin((4, 7))
+PE8 = Pin((4, 8))
+PE9 = Pin((4, 9))
+PE10 = Pin((4, 10))
+PE11 = Pin((4, 11))
+PE12 = Pin((4, 12))
+PE13 = Pin((4, 13))
+PE14 = Pin((4, 14))
+PE15 = Pin((4, 15))
+PF0 = Pin((5, 0))
+PF1 = Pin((5, 1))
+PF2 = Pin((5, 2))
+PF3 = Pin((5, 3))
+PF4 = Pin((5, 4))
+PF5 = Pin((5, 5))
+PF6 = Pin((5, 6))
+PF7 = Pin((5, 7))
+PF8 = Pin((5, 8))
+PF9 = Pin((5, 9))
+PF10 = Pin((5, 10))
+PF11 = Pin((5, 11))
+PF12 = Pin((5, 12))
+PF13 = Pin((5, 13))
+PF14 = Pin((5, 14))
+PF15 = Pin((5, 15))
+PG1 = Pin((6, 1))
+PG2 = Pin((6, 2))
+PG3 = Pin((6, 3))
+PG4 = Pin((6, 4))
+PG5 = Pin((6, 5))
+PG6 = Pin((6, 6))
+PG7 = Pin((6, 7))
+PG8 = Pin((6, 8))
+PG9 = Pin((6, 9))
+PG10 = Pin((6, 10))
+PG11 = Pin((6, 11))
+PG12 = Pin((6, 12))
+PG13 = Pin((6, 13))
+PG14 = Pin((6, 14))
+PG15 = Pin((6, 15))
+PH2 = Pin((7, 2))
+PH3 = Pin((7, 3))
+PH4 = Pin((7, 4))
+PH5 = Pin((7, 5))
+PH6 = Pin((7, 6))
+PH7 = Pin((7, 7))
+PH8 = Pin((7, 8))
+PH9 = Pin((7, 9))
+PH10 = Pin((7, 10))
+PH11 = Pin((7, 11))
+PH12 = Pin((7, 12))
+PH13 = Pin((7, 13))
+PH14 = Pin((7, 14))
+PH15 = Pin((7, 15))
+PI0 = Pin((8, 0))
+PI1 = Pin((8, 1))
+PI2 = Pin((8, 2))
+PI3 = Pin((8, 3))
+PI4 = Pin((8, 4))
+PI5 = Pin((8, 5))
+PI6 = Pin((8, 6))
+PI7 = Pin((8, 7))
+PI8 = Pin((8, 8))
+PI9 = Pin((8, 9))
+PI10 = Pin((8, 10))
+PI11 = Pin((8, 11))
+PZ0 = Pin((9, 0))
+PZ1 = Pin((9, 1))
+PZ2 = Pin((9, 2))
+PZ3 = Pin((9, 3))
+PZ4 = Pin((9, 4))
+PZ5 = Pin((9, 5))
+PZ6 = Pin((9, 6))
+PZ7 = Pin((9, 7))
+
+# ordered as uartId, txId, rxId
+UART_PORTS = ((3, PB10, PB12),)
+
+# ordered as i2cId, sclId, sdaId
+I2C_PORTS = (
+    (1, PD12, PF15),
+    (5, PA11, PA12),
+)
index ba06449636cfad3e22dcbe6a644636ba9a3db0a6..f728a40e26f5a734b8142be40f7a803ce264d0f2 100644 (file)
@@ -82,7 +82,7 @@ SCL = Pin("GPIO_SEN8")
 SDA_1 = Pin("GEN1_I2C_SDA")
 SCL_1 = Pin("GEN1_I2C_SCL")
 
-J04 = Pin("AUD_MCLK")
+# Jetson TX2 specific
 J06 = Pin("GPIO_AUD1")
 AA02 = Pin("CAN_GPIO2")
 N06 = Pin("GPIO_CAM7")
@@ -93,10 +93,6 @@ 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")
@@ -104,6 +100,32 @@ P16 = Pin("GPIO_EXP_P16")
 I04 = Pin("GPIO_PQ4")
 J05 = Pin("GPIO_AUD0")
 
+# Jetson TX2 NX specific
+W04 = Pin("UART3_RTS")
+V01 = Pin("GPIO_SEN1")
+C02 = Pin("DAP2_DOUT")
+C03 = Pin("DAP2_DIN")
+V04 = Pin("GPIO_SEN4")
+H02 = Pin("GPIO_WAN7")
+H01 = Pin("GPIO_WAN6")
+V02 = Pin("GPIO_SEN2")
+H00 = Pin("GPIO_WAN5")
+H03 = Pin("GPIO_WAN8")
+Y03 = Pin("GPIO_MDM4")
+N01 = Pin("GPIO_CAM2")
+EE02 = Pin("TOUCH_CLK")
+U00 = Pin("GPIO_DIS0")
+U05 = Pin("GPIO_DIS5")
+W05 = Pin("UART3_CTS")
+V03 = Pin("GPIO_SEN3")
+
+# Shared pin
+J03 = Pin("DAP1_FS")
+J02 = Pin("DAP1_DIN")
+J01 = Pin("DAP1_DOUT")
+J00 = Pin("DAP1_SCLK")
+J04 = Pin("AUD_MCLK")
+
 i2cPorts = (
     (1, SCL, SDA),
     (0, SCL_1, SDA_1),
index 9a803cbe8daa7022562ee9ac9a6b12ff3778b58b..4bcfff9984064042dc49cb3a4976e0f188684a00 100644 (file)
@@ -111,6 +111,9 @@ Y02 = Pin("SPI3_MOSI")
 T07 = Pin("DAP5_DIN")
 T06 = Pin("DAP5_DOUT")
 
+# Clara AGX Xavier only
+P04 = Pin("SOC_GPIO04")
+
 # Shared
 N01 = Pin("SOC_GPIO54")
 R00 = Pin("SOC_GPIO44")
index f126ef326b9d146d5f5d720a34e26ecca888b8c9..1db939a3fd93465d4f88cb75bf5ae1c4bc190ef2 100644 (file)
@@ -1,10 +1,14 @@
 """
 `analogio` - Analog input and output control
-=================================================
+============================================
 See `CircuitPython:analogio` in CircuitPython for more details.
+Not supported by all boards.
+
 * Author(s): Carter Nelson, Melissa LeBlanc-Williams
 """
 
+import sys
+
 from adafruit_blinka.agnostic import detector
 
 # pylint: disable=ungrouped-imports,wrong-import-position,unused-import
@@ -17,5 +21,11 @@ elif detector.board.greatfet_one:
     from adafruit_blinka.microcontroller.nxp_lpc4330.analogio import AnalogOut
 elif detector.chip.RK3308:
     from adafruit_blinka.microcontroller.generic_linux.sysfs_analogin import AnalogIn
+elif detector.chip.RK3399:
+    from adafruit_blinka.microcontroller.generic_linux.sysfs_analogin import AnalogIn
+elif detector.chip.IMX6ULL:
+    from adafruit_blinka.microcontroller.generic_linux.sysfs_analogin import AnalogIn
+elif "sphinx" in sys.modules:
+    pass
 else:
     raise NotImplementedError("analogio not supported for this board.")
index a9b341deb4fdab98e252987df81d9933539f7f21..a89d70daa8c7aca2c33297a5c1106509158aa53d 100755 (executable)
@@ -50,10 +50,10 @@ elif detector.board.any_raspberry_pi_40_pin:
 elif detector.board.any_raspberry_pi_cm:
     from adafruit_blinka.board.raspberrypi.raspi_cm import *
 
-elif detector.board.RASPBERRY_PI_A or detector.board.RASPBERRY_PI_B_REV1:
+elif detector.board.RASPBERRY_PI_B_REV1:
     from adafruit_blinka.board.raspberrypi.raspi_1b_rev1 import *
 
-elif detector.board.RASPBERRY_PI_B_REV2:
+elif detector.board.RASPBERRY_PI_A or detector.board.RASPBERRY_PI_B_REV2:
     from adafruit_blinka.board.raspberrypi.raspi_1b_rev2 import *
 
 elif board_id == ap_board.BEAGLEBONE_BLACK:
@@ -67,11 +67,16 @@ elif board_id == ap_board.BEAGLEBONE_BLACK_INDUSTRIAL:
 
 elif board_id == ap_board.BEAGLEBONE_GREEN_WIRELESS:
     from adafruit_blinka.board.beagleboard.beaglebone_black import *
+
 elif board_id == ap_board.BEAGLEBONE_BLACK_WIRELESS:
     from adafruit_blinka.board.beagleboard.beaglebone_black import *
+
 elif board_id == ap_board.BEAGLEBONE_POCKETBEAGLE:
     from adafruit_blinka.board.beagleboard.beaglebone_pocketbeagle import *
 
+elif board_id == ap_board.BEAGLEBONE_AI:
+    from adafruit_blinka.board.beagleboard.beaglebone_ai import *
+
 elif board_id == ap_board.ORANGE_PI_PC:
     from adafruit_blinka.board.orangepi.orangepipc import *
 
@@ -96,6 +101,18 @@ elif board_id == ap_board.ORANGE_PI_PLUS_2E:
 elif board_id == ap_board.ORANGE_PI_2:
     from adafruit_blinka.board.orangepi.orangepipc import *
 
+elif board_id == ap_board.ORANGE_PI_ZERO_PLUS_2H5:
+    from adafruit_blinka.board.orangepi.orangepizeroplus2h5 import *
+
+elif board_id == ap_board.ORANGE_PI_ZERO_PLUS:
+    from adafruit_blinka.board.orangepi.orangepizeroplus import *
+
+elif board_id == ap_board.ORANGE_PI_ZERO_2:
+    from adafruit_blinka.board.orangepi.orangepizero2 import *
+
+elif board_id == ap_board.BANANA_PI_M2_ZERO:
+    from adafruit_blinka.board.bananapi.bpim2zero import *
+
 elif board_id == ap_board.GIANT_BOARD:
     from adafruit_blinka.board.giantboard import *
 
@@ -105,6 +122,9 @@ elif board_id == ap_board.JETSON_TX1:
 elif board_id == ap_board.JETSON_TX2:
     from adafruit_blinka.board.nvidia.jetson_tx2 import *
 
+elif board_id == ap_board.JETSON_TX2_NX:
+    from adafruit_blinka.board.nvidia.jetson_tx2_nx import *
+
 elif board_id == ap_board.JETSON_XAVIER:
     from adafruit_blinka.board.nvidia.jetson_xavier import *
 
@@ -114,8 +134,14 @@ elif board_id == ap_board.JETSON_NANO:
 elif board_id == ap_board.JETSON_NX:
     from adafruit_blinka.board.nvidia.jetson_nx import *
 
+elif board_id == ap_board.CLARA_AGX_XAVIER:
+    from adafruit_blinka.board.nvidia.clara_agx_xavier import *
+
 elif board_id == ap_board.CORAL_EDGE_TPU_DEV:
-    from adafruit_blinka.board.coral_edge_tpu import *
+    from adafruit_blinka.board.coral_dev_board import *
+
+elif board_id == ap_board.CORAL_EDGE_TPU_DEV_MINI:
+    from adafruit_blinka.board.coral_dev_board_mini import *
 
 elif board_id == ap_board.ODROID_C2:
     from adafruit_blinka.board.hardkernel.odroidc2 import *
@@ -153,6 +179,12 @@ elif board_id == ap_board.SIFIVE_UNLEASHED:
 elif board_id == ap_board.PINE64:
     from adafruit_blinka.board.pine64 import *
 
+elif board_id == ap_board.PINEH64:
+    from adafruit_blinka.board.pineH64 import *
+
+elif board_id == ap_board.SOPINE:
+    from adafruit_blinka.board.soPine import *
+
 elif board_id == ap_board.CLOCKWORK_CPI3:
     from adafruit_blinka.board.clockworkcpi3 import *
 
@@ -162,6 +194,24 @@ elif board_id == ap_board.ONION_OMEGA2:
 elif board_id == ap_board.ROCK_PI_S:
     from adafruit_blinka.board.radxa.rockpis import *
 
+elif board_id == ap_board.ROCK_PI_4:
+    from adafruit_blinka.board.radxa.rockpi4 import *
+
+elif board_id == ap_board.UDOO_X86:
+    from adafruit_blinka.board.udoo_x86ultra import *
+
+elif board_id == ap_board.STM32MP157C_DK2:
+    from adafruit_blinka.board.stm32.stm32mp157c_dk2 import *
+
+elif board_id == ap_board.LUBANCAT_IMX6ULL:
+    from adafruit_blinka.board.lubancat.lubancat_imx6ull import *
+
+elif board_id == ap_board.NANOPI_NEO_AIR:
+    from adafruit_blinka.board.nanopi.neoair import *
+
+elif board_id == ap_board.NANOPI_DUO2:
+    from adafruit_blinka.board.nanopi.duo2 import *
+
 elif "sphinx" in sys.modules:
     pass
 
index 1ad6e41991abc53b396e61b2af0a1215206b947d..931b43e15e19d9a9edb1926dd9144c715cdd9e78 100755 (executable)
@@ -7,7 +7,10 @@ See `CircuitPython:busio` in CircuitPython for more details.
 * Author(s): cefn
 """
 
-import threading
+try:
+    import threading
+except ImportError:
+    threading = None
 
 import adafruit_platformdetect.constants.boards as ap_board
 import adafruit_platformdetect.constants.chips as ap_chip
@@ -24,7 +27,7 @@ class I2C(Lockable):
     for both MicroPython and Linux.
     """
 
-    def __init__(self, scl, sda, frequency=400000):
+    def __init__(self, scl, sda, frequency=100000):
         self.init(scl, sda, frequency)
 
     def init(self, scl, sda, frequency):
@@ -71,8 +74,8 @@ class I2C(Lockable):
                     (scl, sda), i2cPorts
                 )
             )
-
-        self._lock = threading.RLock()
+        if threading is not None:
+            self._lock = threading.RLock()
 
     def deinit(self):
         """Deinitialization"""
@@ -82,11 +85,13 @@ class I2C(Lockable):
             pass
 
     def __enter__(self):
-        self._lock.acquire()
+        if threading is not None:
+            self._lock.acquire()
         return self
 
     def __exit__(self, exc_type, exc_value, traceback):
-        self._lock.release()
+        if threading is not None:
+            self._lock.release()
         self.deinit()
 
     def scan(self):
@@ -124,7 +129,7 @@ class I2C(Lockable):
         in_end=None,
         stop=False
     ):
-        """"Write to a device at specified address from a buffer then read
+        """ "Write to a device at specified address from a buffer then read
         from a device at specified address into a buffer
         """
         return self._i2c.writeto_then_readfrom(
@@ -197,10 +202,21 @@ class SPI(Lockable):
         if detector.board.any_raspberry_pi or detector.board.any_raspberry_pi_40_pin:
             from adafruit_blinka.microcontroller.bcm283x.pin import Pin
             from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
+        elif detector.board.BEAGLEBONE_AI:
+            from adafruit_blinka.microcontroller.dra74x.pin import Pin
+            from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
         elif detector.board.any_beaglebone:
             from adafruit_blinka.microcontroller.am335x.pin import Pin
             from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
-        elif detector.board.any_orange_pi and detector.chip.id == ap_chip.SUN8I:
+        elif detector.board.any_orange_pi:
+            if detector.chip.id == ap_chip.SUN8I:
+                from adafruit_blinka.microcontroller.allwinner.h3.pin import Pin
+            elif detector.chip.id == ap_chip.H5:
+                from adafruit_blinka.microcontroller.allwinner.h5.pin import Pin
+            elif detector.chip.id == ap_chip.H616:
+                from adafruit_blinka.microcontroller.allwinner.h616.pin import Pin
+            from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
+        elif detector.board.any_nanopi and detector.chip.id == ap_chip.SUN8I:
             from adafruit_blinka.microcontroller.allwinner.h3.pin import Pin
             from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
         elif board_id == ap_board.GIANT_BOARD:
@@ -209,6 +225,9 @@ class SPI(Lockable):
         elif board_id == ap_board.CORAL_EDGE_TPU_DEV:
             from adafruit_blinka.microcontroller.nxp_imx8m.pin import Pin
             from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
+        elif board_id == ap_board.CORAL_EDGE_TPU_DEV_MINI:
+            from adafruit_blinka.microcontroller.mt8167.pin import Pin
+            from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
         elif board_id == ap_board.ODROID_C2:
             from adafruit_blinka.microcontroller.amlogic.s905.pin import Pin
             from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
@@ -239,6 +258,9 @@ class SPI(Lockable):
         elif detector.board.ROCK_PI_S:
             from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
             from adafruit_blinka.microcontroller.rockchip.rk3308.pin import Pin
+        elif detector.board.ROCK_PI_4:
+            from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
+            from adafruit_blinka.microcontroller.rockchip.rk3399.pin import Pin
         elif detector.board.SIFIVE_UNLEASHED:
             from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
             from adafruit_blinka.microcontroller.hfu540.pin import Pin
@@ -254,7 +276,12 @@ class SPI(Lockable):
         elif detector.board.greatfet_one:
             from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
             from adafruit_blinka.microcontroller.nxp_lpc4330.pin import Pin
-        elif board_id in (ap_board.PINE64, ap_board.PINEBOOK, ap_board.PINEPHONE):
+        elif board_id in (
+            ap_board.PINE64,
+            ap_board.PINEBOOK,
+            ap_board.PINEPHONE,
+            ap_board.SOPINE,
+        ):
             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:
@@ -263,6 +290,9 @@ class SPI(Lockable):
         elif board_id == ap_board.ONION_OMEGA2:
             from adafruit_blinka.microcontroller.mips24kec.pin import Pin
             from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
+        elif detector.board.any_lubancat and detector.chip.id == ap_chip.IMX6ULL:
+            from adafruit_blinka.microcontroller.nxp_imx6ull.pin import Pin
+            from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
         else:
             from machine import SPI as _SPI
             from machine import Pin
@@ -295,7 +325,7 @@ class SPI(Lockable):
         except AttributeError:
             raise NotImplementedError(
                 "Frequency attribute not implemented for this platform"
-            )
+            ) from AttributeError
 
     def write(self, buf, start=0, end=None):
         """Write to the SPI device"""
@@ -414,3 +444,36 @@ class UART(Lockable):
     def write(self, buf):
         """Write to the UART from a buffer"""
         return self._uart.write(buf)
+
+
+class OneWire:
+    """
+    Stub class for OneWire, which is currently not implemented
+    """
+
+    def __init__(self, pin):
+        raise NotImplementedError("OneWire has not been implemented")
+
+    def deinit(self):
+        """
+        Deinitialize the OneWire bus and release any hardware resources for reuse.
+        """
+        raise NotImplementedError("OneWire has not been implemented")
+
+    def reset(self):
+        """
+        Reset the OneWire bus and read presence
+        """
+        raise NotImplementedError("OneWire has not been implemented")
+
+    def read_bit(self):
+        """
+        Read in a bit
+        """
+        raise NotImplementedError("OneWire has not been implemented")
+
+    def write_bit(self, value):
+        """
+        Write out a bit based on value.
+        """
+        raise NotImplementedError("OneWire has not been implemented")
index 53df36812a15675c9db2e001a53a556655276afe..8db83991968a91875a915dff3487a886f1cf5639 100755 (executable)
@@ -1,6 +1,6 @@
 """
-`digitalio` - Digital input and output control
-=================================================
+`digitalio` - Digital input and output control (GPIO)
+=====================================================
 
 See `CircuitPython:digitalio` in CircuitPython for more details.
 
@@ -15,6 +15,8 @@ if detector.chip.BCM2XXX:
     from adafruit_blinka.microcontroller.bcm283x.pin import Pin
 elif detector.chip.AM33XX:
     from adafruit_blinka.microcontroller.am335x.pin import Pin
+elif detector.chip.DRA74X:
+    from adafruit_blinka.microcontroller.dra74x.pin import Pin
 elif detector.chip.SUN8I:
     from adafruit_blinka.microcontroller.allwinner.h3.pin import Pin
 elif detector.chip.SAMA5:
@@ -37,6 +39,8 @@ elif detector.chip.APQ8016:
     from adafruit_blinka.microcontroller.snapdragon.apq8016.pin import Pin
 elif detector.chip.IMX8MX:
     from adafruit_blinka.microcontroller.nxp_imx8m.pin import Pin
+elif detector.chip.IMX6ULL:
+    from adafruit_blinka.microcontroller.nxp_imx6ull.pin import Pin
 elif detector.chip.HFU540:
     from adafruit_blinka.microcontroller.hfu540.pin import Pin
 elif detector.chip.A64:
@@ -47,6 +51,8 @@ elif detector.chip.MIPS24KEC:
     from adafruit_blinka.microcontroller.mips24kec.pin import Pin
 elif detector.chip.RK3308:
     from adafruit_blinka.microcontroller.rockchip.rk3308.pin import Pin
+elif detector.chip.RK3399:
+    from adafruit_blinka.microcontroller.rockchip.rk3399.pin import Pin
 elif detector.board.ftdi_ft232h:
     from adafruit_blinka.microcontroller.ftdi_mpsse.ft232h.pin import Pin
 elif detector.board.ftdi_ft2232h:
@@ -55,10 +61,21 @@ elif detector.board.binho_nova:
     from adafruit_blinka.microcontroller.nova.pin import Pin
 elif detector.board.greatfet_one:
     from adafruit_blinka.microcontroller.nxp_lpc4330.pin import Pin
-elif detector.chip.STM32:
+elif detector.chip.STM32F405:
     from machine import Pin
 elif detector.board.microchip_mcp2221:
     from adafruit_blinka.microcontroller.mcp2221.pin import Pin
+elif detector.chip.PENTIUM_N3710:
+    from adafruit_blinka.microcontroller.pentium.n3710.pin import Pin
+elif detector.chip.STM32MP157:
+    from adafruit_blinka.microcontroller.stm32.stm32mp157.pin import Pin
+elif detector.chip.MT8167:
+    from adafruit_blinka.microcontroller.mt8167.pin import Pin
+elif detector.chip.H5:
+    from adafruit_blinka.microcontroller.allwinner.h5.pin import Pin
+elif detector.chip.H616:
+    from adafruit_blinka.microcontroller.allwinner.h616.pin import Pin
+
 from adafruit_blinka import Enum, ContextManaged
 
 
index f40d9f0a37218335cfe85991ed66127889b7ce41..56396a00463b6186260250f552e326c38bed9129 100755 (executable)
@@ -1,10 +1,17 @@
 """Microcontroller pins"""
 
+import time
+
 from adafruit_platformdetect.constants import chips as ap_chip
 from adafruit_blinka import Enum
 from adafruit_blinka.agnostic import board_id, chip_id
 
 
+def delay_us(delay):
+    """Sleep for delay usecs."""
+    time.sleep(delay / 1e6)
+
+
 class Pin(Enum):
     """Reference Pin object"""
 
@@ -13,7 +20,7 @@ class Pin(Enum):
         self._id = pin_id
 
     def __repr__(self):
-        # pylint: disable=import-outside-toplevel
+        # pylint: disable=import-outside-toplevel, cyclic-import
         import board
 
         for key in dir(board):
@@ -21,7 +28,7 @@ class Pin(Enum):
                 return "board.{}".format(key)
         import microcontroller.pin as pin
 
-        # pylint: enable=import-outside-toplevel
+        # pylint: enable=import-outside-toplevel, cyclic-import
 
         for key in dir(pin):
             if getattr(pin, key) is self:
@@ -34,14 +41,20 @@ class Pin(Enum):
 
 if chip_id == ap_chip.ESP8266:
     from adafruit_blinka.microcontroller.esp8266 import *
-elif chip_id == ap_chip.STM32:
-    from adafruit_blinka.microcontroller.stm32 import *
+elif chip_id == ap_chip.STM32F405:
+    from adafruit_blinka.microcontroller.stm32.stm32f405 import *
 elif chip_id == ap_chip.BCM2XXX:
     from adafruit_blinka.microcontroller.bcm283x import *
+elif chip_id == ap_chip.DRA74X:
+    from adafruit_blinka.microcontroller.dra74x.pin import *
 elif chip_id == ap_chip.AM33XX:
     from adafruit_blinka.microcontroller.am335x import *
 elif chip_id == ap_chip.SUN8I:
     from adafruit_blinka.microcontroller.allwinner.h3 import *
+elif chip_id == ap_chip.H5:
+    from adafruit_blinka.microcontroller.allwinner.h5.pin import *
+elif chip_id == ap_chip.H616:
+    from adafruit_blinka.microcontroller.allwinner.h616.pin import *
 elif chip_id == ap_chip.SAMA5:
     from adafruit_blinka.microcontroller.sama5 import *
 elif chip_id == ap_chip.T210:
@@ -66,8 +79,14 @@ elif chip_id == ap_chip.A33:
     from adafruit_blinka.microcontroller.allwinner.a33.pin import *
 elif chip_id == ap_chip.RK3308:
     from adafruit_blinka.microcontroller.rockchip.rk3308.pin import *
+elif chip_id == ap_chip.RK3399:
+    from adafruit_blinka.microcontroller.rockchip.rk3399.pin import *
+elif chip_id == ap_chip.H5:
+    from adafruit_blinka.microcontroller.allwinner.h5.pin import *
 elif chip_id == ap_chip.IMX8MX:
     from adafruit_blinka.microcontroller.nxp_imx8m import *
+elif chip_id == ap_chip.IMX6ULL:
+    from adafruit_blinka.microcontroller.nxp_imx6ull import *
 elif chip_id == ap_chip.HFU540:
     from adafruit_blinka.microcontroller.hfu540.pin import *
 elif chip_id == ap_chip.BINHO:
@@ -82,5 +101,11 @@ elif chip_id == ap_chip.FT232H:
     from adafruit_blinka.microcontroller.ftdi_mpsse.ft232h.pin import *
 elif chip_id == ap_chip.FT2232H:
     from adafruit_blinka.microcontroller.ftdi_mpsse.ft2232h.pin import *
+elif chip_id == ap_chip.PENTIUM_N3710:
+    from adafruit_blinka.microcontroller.pentium.n3710.pin import *
+elif chip_id == ap_chip.STM32MP157:
+    from adafruit_blinka.microcontroller.stm32.stm32mp157.pin import *
+elif chip_id == ap_chip.MT8167:
+    from adafruit_blinka.microcontroller.mt8167.pin import *
 else:
     raise NotImplementedError("Microcontroller not supported:", chip_id)
index 5b8bc41387d31902b2970e66bf4a308161721b6e..8cdf89b3b3cfe4a7c0f79ba67fc1c88788a27bd9 100755 (executable)
@@ -8,14 +8,20 @@ from adafruit_blinka.agnostic import chip_id
 
 if chip_id == ap_chip.ESP8266:
     from adafruit_blinka.microcontroller.esp8266.pin import *
-elif chip_id == ap_chip.STM32:
-    from adafruit_blinka.microcontroller.stm32.pin import *
+elif chip_id == ap_chip.STM32F405:
+    from adafruit_blinka.microcontroller.stm32.stm32f405.pin import *
 elif chip_id == ap_chip.BCM2XXX:
     from adafruit_blinka.microcontroller.bcm283x.pin import *
+elif chip_id == ap_chip.DRA74X:
+    from adafruit_blinka.microcontroller.dra74x.pin import *
 elif chip_id == ap_chip.AM33XX:
     from adafruit_blinka.microcontroller.am335x.pin import *
 elif chip_id == ap_chip.SUN8I:
     from adafruit_blinka.microcontroller.allwinner.h3.pin import *
+elif chip_id == ap_chip.H5:
+    from adafruit_blinka.microcontroller.allwinner.h5.pin import *
+elif chip_id == ap_chip.H616:
+    from adafruit_blinka.microcontroller.allwinner.h616.pin import *
 elif chip_id == ap_chip.SAMA5:
     from adafruit_blinka.microcontroller.sama5.pin import *
 elif chip_id == ap_chip.T210:
@@ -36,6 +42,8 @@ elif chip_id == ap_chip.APQ8016:
     from adafruit_blinka.microcontroller.snapdragon.apq8016.pin import *
 elif chip_id == ap_chip.IMX8MX:
     from adafruit_blinka.microcontroller.nxp_imx8m.pin import *
+elif chip_id == ap_chip.IMX6ULL:
+    from adafruit_blinka.microcontroller.nxp_imx6ull.pin import *
 elif chip_id == ap_chip.HFU540:
     from adafruit_blinka.microcontroller.hfu540.pin import *
 elif chip_id == ap_chip.FT232H:
@@ -54,9 +62,17 @@ elif chip_id == ap_chip.A33:
     from adafruit_blinka.microcontroller.allwinner.a33.pin import *
 elif chip_id == ap_chip.RK3308:
     from adafruit_blinka.microcontroller.rockchip.rk3308.pin import *
+elif chip_id == ap_chip.RK3399:
+    from adafruit_blinka.microcontroller.rockchip.rk3399.pin import *
 elif chip_id == ap_chip.MIPS24KC:
     from adafruit_blinka.microcontroller.atheros.ar9331.pin import *
 elif chip_id == ap_chip.MIPS24KEC:
     from adafruit_blinka.microcontroller.mips24kec.pin import *
+elif chip_id == ap_chip.PENTIUM_N3710:
+    from adafruit_blinka.microcontroller.pentium.n3710.pin import *
+elif chip_id == ap_chip.STM32MP157:
+    from adafruit_blinka.microcontroller.stm32.stm32mp157.pin import *
+elif chip_id == ap_chip.MT8167:
+    from adafruit_blinka.microcontroller.mt8167.pin import *
 else:
     raise NotImplementedError("Microcontroller not supported: ", chip_id)
index 5626bc632bace3df0884ecfad19edc8c210310f5..2c85f0166ff1b79555e6127563b6c7f78155bb16 100644 (file)
@@ -1,8 +1,9 @@
 """
 `neopixel_write` - NeoPixel precision timed writing support
-=================================================
+===========================================================
 
 See `CircuitPython:neopixel_write` in CircuitPython for more details.
+Currently supported on Raspberry Pi only.
 
 * Author(s): ladyada
 """
index ab44c69e360723817cf761a94e52f7a6f83f6b4b..dc20e3dc029ab97207794897584b41925fa1b4f6 100644 (file)
@@ -1,25 +1,36 @@
 """
-`pulseio` - Pulse Width Modulation Input and Output control
-=================================================
+`pulseio` - Pulse Width Modulation input and output control
+===========================================================
 See `CircuitPython:pulseio` in CircuitPython for more details.
+Not supported by all boards.
+
 * Author(s): Melissa LeBlanc-Williams
 """
 
+import sys
+
 from adafruit_blinka.agnostic import detector
 
 # pylint: disable=unused-import
 
 if detector.board.any_raspberry_pi:
     from adafruit_blinka.microcontroller.bcm283x.pulseio.PulseIn import PulseIn
-if detector.board.any_coral_board:
+    from adafruit_blinka.microcontroller.bcm283x.pulseio.PWMOut import PWMOut
+elif detector.board.any_coral_board:
     from adafruit_blinka.microcontroller.generic_linux.sysfs_pwmout import PWMOut
-if detector.board.any_giant_board:
+elif detector.board.any_giant_board:
     from adafruit_blinka.microcontroller.generic_linux.sysfs_pwmout import PWMOut
-if detector.board.any_beaglebone:
+elif detector.board.any_beaglebone:
     from adafruit_blinka.microcontroller.am335x.sysfs_pwmout import PWMOut
-if detector.board.any_rock_pi_board:
+elif detector.board.any_rock_pi_board:
     from adafruit_blinka.microcontroller.generic_linux.sysfs_pwmout import PWMOut
-if detector.board.binho_nova:
+elif detector.board.binho_nova:
     from adafruit_blinka.microcontroller.nova.pwmout import PWMOut
-if detector.board.greatfet_one:
+elif detector.board.greatfet_one:
     from adafruit_blinka.microcontroller.nxp_lpc4330.pwmout import PWMOut
+elif detector.board.any_lubancat:
+    from adafruit_blinka.microcontroller.generic_linux.sysfs_pwmout import PWMOut
+elif "sphinx" in sys.modules:
+    pass
+else:
+    raise NotImplementedError("pulseio not supported for this board.")
diff --git a/src/pwmio.py b/src/pwmio.py
new file mode 100644 (file)
index 0000000..3a6b5bd
--- /dev/null
@@ -0,0 +1,35 @@
+"""
+`pwmio` - Support for PWM based protocols
+===========================================================
+See `CircuitPython:pwmio` in CircuitPython for more details.
+Not supported by all boards.
+
+* Author(s): Melissa LeBlanc-Williams
+"""
+
+import sys
+
+from adafruit_blinka.agnostic import detector
+
+# pylint: disable=unused-import
+
+if detector.board.any_raspberry_pi:
+    from adafruit_blinka.microcontroller.bcm283x.pulseio.PWMOut import PWMOut
+elif detector.board.any_coral_board:
+    from adafruit_blinka.microcontroller.generic_linux.sysfs_pwmout import PWMOut
+elif detector.board.any_giant_board:
+    from adafruit_blinka.microcontroller.generic_linux.sysfs_pwmout import PWMOut
+elif detector.board.any_beaglebone:
+    from adafruit_blinka.microcontroller.am335x.sysfs_pwmout import PWMOut
+elif detector.board.any_rock_pi_board:
+    from adafruit_blinka.microcontroller.rockchip.PWMOut import PWMOut
+elif detector.board.binho_nova:
+    from adafruit_blinka.microcontroller.nova.pwmout import PWMOut
+elif detector.board.greatfet_one:
+    from adafruit_blinka.microcontroller.nxp_lpc4330.pwmout import PWMOut
+elif detector.board.any_lubancat:
+    from adafruit_blinka.microcontroller.generic_linux.sysfs_pwmout import PWMOut
+elif "sphinx" in sys.modules:
+    pass
+else:
+    raise NotImplementedError("pwmio not supported for this board.")
index 5ad38e21d1d83816ed2263a24da828291a416751..3fcecc34c4f603e97ca8dd4bccb6e30f3c56e243 100644 (file)
@@ -3,8 +3,8 @@ import unittest
 
 class TestEnum(unittest.TestCase):
     """
-        Verifies the repl() and str() behaviour of an example Enum
-        Enums represent configuration values such as digitalio.Direction, digitalio.Pull etc.
+    Verifies the repl() and str() behaviour of an example Enum
+    Enums represent configuration values such as digitalio.Direction, digitalio.Pull etc.
     """
 
     def setUp(self):
@@ -24,7 +24,13 @@ class TestEnum(unittest.TestCase):
     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),])
+        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"""