From f428437e20ab70348ebfc14a9d52873ff55690cf Mon Sep 17 00:00:00 2001 From: KB Sriram Date: Fri, 29 Mar 2024 22:09:21 -0700 Subject: [PATCH 1/4] Fix lint issues and add license so CI builds. --- LICENSES/BSD-3-Clause.txt | 26 +++++++++++ adafruit_pio_uart.py | 81 ++++++++++++++++++++------------- examples/pio_uart_simpletest.py | 1 + 3 files changed, 76 insertions(+), 32 deletions(-) create mode 100644 LICENSES/BSD-3-Clause.txt diff --git a/LICENSES/BSD-3-Clause.txt b/LICENSES/BSD-3-Clause.txt new file mode 100644 index 0000000..f49e084 --- /dev/null +++ b/LICENSES/BSD-3-Clause.txt @@ -0,0 +1,26 @@ +Copyright 2020 (c) 2020 Raspberry Pi (Trading) Ltd. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/adafruit_pio_uart.py b/adafruit_pio_uart.py index 03d6e9c..426e90b 100644 --- a/adafruit_pio_uart.py +++ b/adafruit_pio_uart.py @@ -16,24 +16,29 @@ * Author(s): Scott Shawcroft """ -import adafruit_pioasm import array +import time + +import adafruit_pioasm import busio import rp2pio -import time __version__ = "0.0.0+auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PIO_UART.git" class UART: + """PIO implementation of CircuitPython UART API.""" + Parity = busio.UART.Parity - def __init__(self, tx=None, rx=None, baudrate=9600, bits=8, parity=None, stop=1, timeout=1): + def __init__( + self, tx=None, rx=None, baudrate=9600, bits=8, parity=None, stop=1, timeout=1 + ): # pylint: disable=invalid-name, too-many-arguments self.bitcount = bits + (1 if parity else 0) self.bits = bits self.parity = parity - self.mask = ((1 << bits) - 1) + self.mask = (1 << bits) - 1 self.shift = 8 - (self.bitcount % 8) self._timeout = timeout self.rx_pio = None @@ -50,19 +55,18 @@ def __init__(self, tx=None, rx=None, baudrate=9600, bits=8, parity=None, stop=1, # * Sample data # * Each iteration is 8 cycles rx_code = adafruit_pioasm.assemble( - ".program uart_rx_mini\n" + - "start:\n" - " wait 0 pin 0\n" + - f" set x, {self.bitcount - 1} [10]\n" + - "bitloop:\n" + - " in pins, 1\n" + - " jmp x-- bitloop [6]\n" + - " jmp pin good_stop\n" + - # Skip IRQ - " wait 1 pin 0\n" + - " jmp start\n" + - "good_stop:\n" + - " push\n" + ".program uart_rx_mini\n" + + "start:\n" + + " wait 0 pin 0\n" + + f" set x, {self.bitcount - 1} [10]\n" + + "bitloop:\n" + + " in pins, 1\n" + + " jmp x-- bitloop [6]\n" + + " jmp pin good_stop\n" + + " wait 1 pin 0\n" # Skip IRQ + + " jmp start\n" + + "good_stop:\n" + + " push\n" ) self.rx_pio = rp2pio.StateMachine( rx_code, @@ -70,7 +74,7 @@ def __init__(self, tx=None, rx=None, baudrate=9600, bits=8, parity=None, stop=1, jmp_pin=rx, frequency=8 * baudrate, auto_push=False, - push_threshold=self.bitcount + push_threshold=self.bitcount, ) self.tx_pio = None @@ -86,13 +90,13 @@ def __init__(self, tx=None, rx=None, baudrate=9600, bits=8, parity=None, stop=1, # * Shift 1 bit from OSR to the first OUT pin # * Each loop iteration is 8 cycles. tx_code = adafruit_pioasm.Program( - ".program uart_tx\n" + - ".side_set 1 opt\n" + - f" pull side 1 [{stop_delay}]\n" + - f" set x, {self.bitcount - 1} side 0 [7]\n" + - "bitloop:\n" + - " out pins, 1\n" + - " jmp x-- bitloop [6]\n" + ".program uart_tx\n" + + ".side_set 1 opt\n" + + f" pull side 1 [{stop_delay}]\n" + + f" set x, {self.bitcount - 1} side 0 [7]\n" + + "bitloop:\n" + + " out pins, 1\n" + + " jmp x-- bitloop [6]\n" ) self.tx_pio = rp2pio.StateMachine( tx_code.assembled, @@ -107,6 +111,7 @@ def __init__(self, tx=None, rx=None, baudrate=9600, bits=8, parity=None, stop=1, ) def deinit(self): + """De-initialize the UART object.""" if self.rx_pio: self.rx_pio.deinit() if self.tx_pio: @@ -114,20 +119,24 @@ def deinit(self): @property def timeout(self): + """Return the UART timeout.""" return self._timeout @timeout.setter def timeout(self, value): + """Set the UART timeout.""" self._timeout = value @property def baudrate(self): + """Return the UART baudrate.""" if self.tx_pio: return self.tx_pio.frequency // 8 return self.rx_pio.frequency // 8 @baudrate.setter def baudrate(self, frequency): + """Set the UART baudrate.""" if self.rx_pio: self.rx_pio.frequency = frequency * 8 if self.tx_pio: @@ -135,35 +144,41 @@ def baudrate(self, frequency): @property def in_waiting(self): + """Return whether the UART is waiting.""" return self.rx_pio.in_waiting def reset_input_buffer(self): + """Clear the UART input buffer.""" self.rx_pio.clear_rxfifo() def readinto(self, buf): + """Read UART data into buf and return the number of bytes read.""" if self.bitcount > 8: raw_in = array.array("H") for _ in range(len(buf)): raw_in.append(0) else: raw_in = buf - mv = memoryview(raw_in) + mem_view = memoryview(raw_in) count = 0 start_time = time.monotonic() - while count < len(buf) and (self.timeout == 0 or (time.monotonic() - start_time) < self.timeout): + while count < len(buf) and ( + self.timeout == 0 or (time.monotonic() - start_time) < self.timeout + ): waiting = min(len(buf) - count, self.rx_pio.in_waiting) - self.rx_pio.readinto(mv[count:count+waiting]) + self.rx_pio.readinto(mem_view[count : count + waiting]) if self.timeout == 0 and waiting == 0: return None if count == 0 else count count += waiting - if self.parity != None: + if self.parity is not None: for i in range(count): # TODO: Check parity bits instead of just masking them. buf[i] = (raw_in[i] >> self.shift) & self.mask return count def read(self, n): + """Read and return an array of up to n values from the UART.""" if self.bits > 8: buf = array.array(n) else: @@ -174,11 +189,12 @@ def read(self, n): return buf def write(self, buf): + """Write the contents of buf to the UART.""" # Compute parity if we need to if self.parity: if self.bitcount > 8: - a = array.array("H") - for i, v in enumerate(buf): + a = array.array("H") # pylint: disable=invalid-name + for i, v in enumerate(buf): # pylint: disable=invalid-name a.append(v) ones = 0 for pos in range(self.bitcount - 1): @@ -188,7 +204,8 @@ def write(self, buf): if self.parity == self.Parity.ODD: if (ones % 2) == 0: parity = 1 - elif (ones % 2) == 1: # even parity needs another one if the data is odd + elif (ones % 2) == 1: + # even parity needs another one if the data is odd parity = 1 a[i] |= parity << (self.bitcount - 1) buf = a diff --git a/examples/pio_uart_simpletest.py b/examples/pio_uart_simpletest.py index c83b10a..a2733b6 100644 --- a/examples/pio_uart_simpletest.py +++ b/examples/pio_uart_simpletest.py @@ -2,6 +2,7 @@ # # SPDX-License-Identifier: Unlicense +import board import adafruit_pio_uart uart = adafruit_pio_uart.UART(board.TX, board.RX) From 2229b5e0ef62c5e29e45c64271a1fed89ccf8aad Mon Sep 17 00:00:00 2001 From: KB Sriram Date: Fri, 29 Mar 2024 22:19:00 -0700 Subject: [PATCH 2/4] Update requirements.txt to include pioasm. --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 3b4e055..d937b1f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,4 @@ # SPDX-License-Identifier: MIT Adafruit-Blinka +adafruit-circuitpython-pioasm From cac0491820fda15338750ae99fd3912242ad0bb7 Mon Sep 17 00:00:00 2001 From: KB Sriram Date: Sun, 31 Mar 2024 15:04:51 -0700 Subject: [PATCH 3/4] Mock rp2pio imports and update todos in docs. --- README.rst | 16 +++++++--------- docs/conf.py | 1 + docs/index.rst | 6 +----- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/README.rst b/README.rst index 465b0cb..79ca5bc 100644 --- a/README.rst +++ b/README.rst @@ -29,6 +29,7 @@ Dependencies This driver depends on: * `Adafruit CircuitPython `_ +* `Adafruit CircuitPython PIOASM `_ Please ensure all dependencies are available on the CircuitPython filesystem. This is easily achieved by downloading @@ -36,20 +37,15 @@ This is easily achieved by downloading or individual libraries can be installed using `circup `_. +Works with the Raspberry Pi RP2040 Pico family. - -.. todo:: Describe the Adafruit product this library works with. For PCBs, you can also add the -image from the assets folder in the PCB's GitHub repo. - -`Purchase one from the Adafruit shop `_ +`Purchase one from the Adafruit shop `_. Installing from PyPI ===================== .. note:: This library is not available on PyPI yet. Install documentation is included as a standard element. Stay tuned for PyPI availability! -.. todo:: Remove the above note if PyPI version is/will be available at time of release. - On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally `from PyPI `_. To install for current user: @@ -99,8 +95,10 @@ Or the following command to update an existing version: Usage Example ============= -.. todo:: Add a quick, simple example. It and other examples should live in the -examples folder and be included in docs/examples.rst. +.. literalinclude:: ../examples/pio_uart_simpletest.py + :caption: examples/pio_uart_simpletest.py + :linenos: + Documentation ============= diff --git a/docs/conf.py b/docs/conf.py index 9e7b3f9..bc7bf72 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -28,6 +28,7 @@ # 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 = ["digitalio", "busio"] +autodoc_mock_imports = ["rp2pio"] autodoc_preserve_defaults = True diff --git a/docs/index.rst b/docs/index.rst index 4be54e9..39dcc4b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -24,14 +24,10 @@ Table of Contents .. toctree:: :caption: Tutorials -.. todo:: Add any Learn guide links here. If there are none, then simply delete this todo and leave - the toctree above for use later. - .. toctree:: :caption: Related Products -.. todo:: Add any product links here. If there are none, then simply delete this todo and leave - the toctree above for use later. + Adafruit Raspberry Pi RP2040 Pico products .. toctree:: :caption: Other Links From cabbef5eb99c9f765cef8f383c2e6faa3ea8bd3d Mon Sep 17 00:00:00 2001 From: KB Sriram Date: Sun, 31 Mar 2024 15:19:51 -0700 Subject: [PATCH 4/4] Include sample example directly in the README. --- README.rst | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 79ca5bc..0675114 100644 --- a/README.rst +++ b/README.rst @@ -95,9 +95,15 @@ Or the following command to update an existing version: Usage Example ============= -.. literalinclude:: ../examples/pio_uart_simpletest.py - :caption: examples/pio_uart_simpletest.py - :linenos: +.. code-block:: python + + import board + import adafruit_pio_uart + + uart = adafruit_pio_uart.UART(board.TX, board.RX) + + uart.write(b"\x00") + print(uart.read(1)) Documentation