Merge remote-tracking branch 'origin/main' into program-object

This commit is contained in:
Jeff Epler 2022-01-12 08:38:43 -06:00
commit 666f4ef2c9
No known key found for this signature in database
GPG key ID: D5BF15AB975AB4DE
5 changed files with 54 additions and 8 deletions

1
.gitignore vendored
View file

@ -16,3 +16,4 @@ bundles
dist
**/*.egg-info
.vscode
.venv

View file

@ -32,8 +32,6 @@ This is easily achieved by downloading
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!
On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally `from
PyPI <https://pypi.org/project/adafruit-circuitpython-pioasm/>`_. To install for current user:

View file

@ -115,7 +115,12 @@ class Program: # pylint: disable=too-few-public-methods
raise SyntaxError(f"Invalid jmp target {repr(target)}")
if len(instruction) > 2:
try:
assembled[-1] |= CONDITIONS.index(instruction[1]) << 5
except ValueError as exc:
raise ValueError(
f"Invalid jmp condition '{instruction[1]}'"
) from exc
elif instruction[0] == "wait":
# instr delay p sr index
@ -163,7 +168,10 @@ class Program: # pylint: disable=too-few-public-methods
source = instruction[-1]
source_split = mov_splitter(source)
if len(source_split) == 1:
try:
assembled[-1] |= MOV_SOURCES.index(source)
except ValueError as exc:
raise ValueError(f"Invalid mov source '{source}'") from exc
else:
assembled[-1] |= MOV_SOURCES.index(source_split[1])
if source[:1] == "!":
@ -195,7 +203,10 @@ class Program: # pylint: disable=too-few-public-methods
elif instruction[0] == "set":
# instr delay dst data
assembled.append(0b111_00000_000_00000)
try:
assembled[-1] |= SET_DESTINATIONS.index(instruction[1]) << 5
except ValueError as exc:
raise ValueError(f"Invalid set destination '{instruction[1]}'") from exc
value = int(instruction[-1])
if not 0 <= value <= 31:
raise RuntimeError("Set value out of range")

View file

@ -24,6 +24,7 @@ Table of Contents
:caption: Tutorials
Getting Started with Raspberry Pi Pico and CircuitPython <https://learn.adafruit.com/getting-started-with-raspberry-pi-pico-circuitpython>
An Introduction to RP2040 PIO with CircuitPython <https://learn.adafruit.com/intro-to-rp2040-pio-with-circuitpython>
.. toctree::
:caption: Related Products

View file

@ -18,7 +18,7 @@ def nice_opcode(o):
return o[:3] + "_" + o[3:8] + "_" + o[8:]
class TestNop(unittest.TestCase):
class AssembleChecks(unittest.TestCase):
def assertAssemblesTo(self, source, expected):
actual = adafruit_pioasm.assemble(source)
expected_bin = [nice_opcode(x) for x in expected]
@ -29,13 +29,18 @@ class TestNop(unittest.TestCase):
f"Assembling {source!r}: Expected {expected_bin}, got {actual_bin}",
)
def assertAssemblyFails(self, source):
self.assertRaises(RuntimeError, adafruit_pioasm.assemble, source)
def assertAssemblyFails(self, source, match=None, errtype=RuntimeError):
if match:
self.assertRaisesRegex(errtype, match, adafruit_pioasm.assemble, source)
else:
self.assertRaises(errtype, adafruit_pioasm.assemble, source)
def assertPioKwargs(self, source, **kw):
program = adafruit_pioasm.Program(source)
self.assertEqual(kw, program.pio_kwargs)
class TestNop(AssembleChecks):
def testNonsense(self):
self.assertAssemblyFails("nope")
@ -64,6 +69,12 @@ class TestNop(unittest.TestCase):
".side_set 1 opt\nnop side 0 [7]", [0b101_10111_010_00_010]
)
def testSet(self):
# non happy path
self.assertAssemblyFails(
"set isr, 1", match="Invalid set destination 'isr'", errtype=ValueError
)
def testJmp(self):
self.assertAssemblesTo("l:\njmp l", [0b000_00000_000_00000])
self.assertAssemblesTo("l:\njmp 7", [0b000_00000_000_00111])
@ -75,6 +86,10 @@ class TestNop(unittest.TestCase):
self.assertAssemblesTo("jmp x!=y, l\nl:", [0b000_00000_101_00001])
self.assertAssemblesTo("jmp pin, l\nl:", [0b000_00000_110_00001])
self.assertAssemblesTo("jmp !osre, l\nl:", [0b000_00000_111_00001])
# non happy path
self.assertAssemblyFails(
"jmp x--., l\nl:", match="Invalid jmp condition 'x--.'", errtype=ValueError
)
def testWait(self):
self.assertAssemblesTo("wait 0 gpio 0", [0b001_00000_0_00_00000])
@ -99,3 +114,23 @@ class TestNop(unittest.TestCase):
self.assertPioKwargs("", sideset_count=0, sideset_enable=False)
self.assertPioKwargs(".side_set 1", sideset_count=1, sideset_enable=False)
self.assertPioKwargs(".side_set 3 opt", sideset_count=3, sideset_enable=True)
class TestMov(AssembleChecks):
def testMovNonHappy(self):
# non happy path
self.assertAssemblyFails(
"mov x, blah", match="Invalid mov source 'blah'", errtype=ValueError
)
def testMovInvert(self):
# test moving and inverting
self.assertAssemblesTo("mov x, ~ x", [0b101_00000_001_01_001])
self.assertAssemblesTo("mov x, ~ x", [0b101_00000_001_01_001])
self.assertAssemblesTo("mov x, ~x", [0b101_00000_001_01_001])
self.assertAssemblesTo("mov x, !x", [0b101_00000_001_01_001])
def testMovReverse(self):
# test moving and reversing bits
self.assertAssemblesTo("mov x, :: x", [0b101_00000_001_10_001])
self.assertAssemblesTo("mov x, ::x", [0b101_00000_001_10_001])