Merge remote-tracking branch 'origin/main' into program-object
This commit is contained in:
commit
666f4ef2c9
5 changed files with 54 additions and 8 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -16,3 +16,4 @@ bundles
|
|||
dist
|
||||
**/*.egg-info
|
||||
.vscode
|
||||
.venv
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
|
|
|
|||
Loading…
Reference in a new issue