Skip to content

Fix lint issues and add license so CI builds. #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions LICENSES/BSD-3-Clause.txt
Original file line number Diff line number Diff line change
@@ -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.
22 changes: 13 additions & 9 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,23 @@ Dependencies
This driver depends on:

* `Adafruit CircuitPython <https://github.com/adafruit/circuitpython>`_
* `Adafruit CircuitPython PIOASM <https://github.com/adafruit/Adafruit_CircuitPython_PIOASM>`_

Please ensure all dependencies are available on the CircuitPython filesystem.
This is easily achieved by downloading
`the Adafruit library and driver bundle <https://circuitpython.org/libraries>`_
or individual libraries can be installed using
`circup <https://github.com/adafruit/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 <http://www.adafruit.com/products/>`_
`Purchase one from the Adafruit shop <https://www.adafruit.com/category/875>`_.

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 <https://pypi.org/project/adafruit-circuitpython-pio-uart/>`_.
To install for current user:
Expand Down Expand Up @@ -99,8 +95,16 @@ 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.
.. 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
=============
Expand Down
81 changes: 49 additions & 32 deletions adafruit_pio_uart.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -50,27 +55,26 @@ 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,
first_in_pin=rx,
jmp_pin=rx,
frequency=8 * baudrate,
auto_push=False,
push_threshold=self.bitcount
push_threshold=self.bitcount,
)

self.tx_pio = None
Expand All @@ -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,
Expand All @@ -107,63 +111,74 @@ 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:
self.tx_pio.deinit()

@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:
self.tx_pio.frequency = frequency * 8

@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:
Expand All @@ -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):
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
6 changes: 1 addition & 5 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://www.adafruit.com/category/875>

.. toctree::
:caption: Other Links
Expand Down
1 change: 1 addition & 0 deletions examples/pio_uart_simpletest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#
# SPDX-License-Identifier: Unlicense

import board
import adafruit_pio_uart

uart = adafruit_pio_uart.UART(board.TX, board.RX)
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
# SPDX-License-Identifier: MIT

Adafruit-Blinka
adafruit-circuitpython-pioasm