diff --git a/adafruit_pioasm.py b/adafruit_pioasm.py index 6471db7..8ed258a 100644 --- a/adafruit_pioasm.py +++ b/adafruit_pioasm.py @@ -147,7 +147,11 @@ def __init__(self, text_program: str, *, build_debuginfo=False) -> None: elif instruction[0] == "in": # instr delay src count assembled.append(0b010_00000_000_00000) - assembled[-1] |= IN_SOURCES.index(instruction[1]) << 5 + source = instruction[1] + try: + assembled[-1] |= IN_SOURCES.index(source) << 5 + except ValueError as exc: + raise ValueError(f"Invalid in source '{source}'") from exc count = int(instruction[-1], 0) if not 1 <= count <= 32: raise RuntimeError("Count out of range") @@ -155,7 +159,13 @@ def __init__(self, text_program: str, *, build_debuginfo=False) -> None: elif instruction[0] == "out": # instr delay dst count assembled.append(0b011_00000_000_00000) - assembled[-1] |= OUT_DESTINATIONS.index(instruction[1]) << 5 + destination = instruction[1] + try: + assembled[-1] |= OUT_DESTINATIONS.index(destination) << 5 + except ValueError as exc: + raise ValueError( + f"Invalid out destination '{destination}'" + ) from exc count = int(instruction[-1], 0) if not 1 <= count <= 32: raise RuntimeError("Count out of range") diff --git a/tests/test_in.py b/tests/test_in.py new file mode 100644 index 0000000..d2b76dd --- /dev/null +++ b/tests/test_in.py @@ -0,0 +1,69 @@ +# SPDX-FileCopyrightText: KB Sriram +# +# SPDX-License-Identifier: MIT + +""" +Tests in +""" + +import pytest +from pytest_helpers import assert_assembles_to, assert_assembly_fails + + +@pytest.mark.parametrize( + "source,expected", + [ + ("pins", 0b000), + ("x", 0b001), + ("y", 0b010), + ("null", 0b011), + ("isr", 0b110), + ("osr", 0b111), + ], +) +def test_in_sources(source: str, expected: int) -> None: + # delay src bitcount + encoding = 0b010_00000_000_10001 + # add in the expected source + encoding |= expected << 5 + assert_assembles_to(f"in {source}, 17", [encoding]) + + +@pytest.mark.parametrize("delay", [0, 1, 9, 17, 31]) +def test_in_delay(delay: int) -> None: + # delay src bitcount + encoding = 0b010_00000_000_10001 + # add in the expected delay + encoding |= delay << 8 + assert_assembles_to(f"in pins, 17 [{delay}]", [encoding]) + + +@pytest.mark.parametrize("bitcount", [1, 9, 17, 32]) +def test_in_bitcount(bitcount: int) -> None: + # delay dst bitcount + encoding = 0b010_00000_000_00000 + # add in the expected bitcount. Note that + # 32 should be encoded as 0, which we do by + # masking the bitcount with 0x1f + encoding |= bitcount & 0x1F + assert_assembles_to(f"in pins, {bitcount}", [encoding]) + + +def test_in_delay_with_sideset() -> None: + source = [ + ".side_set 2", + "in pins 17 side 2 [5]", + ] + assert_assembles_to("\n".join(source), [0b010_10_101_000_10001]) + + +def test_in_bad_source(): + assert_assembly_fails( + "in bad, 17", match="Invalid in source 'bad'", errtype=ValueError + ) + + +def test_in_bad_bitcount(): + assert_assembly_fails( + "in pins, 0", match="Count out of range", errtype=RuntimeError + ) diff --git a/tests/test_out.py b/tests/test_out.py new file mode 100644 index 0000000..5956fce --- /dev/null +++ b/tests/test_out.py @@ -0,0 +1,71 @@ +# SPDX-FileCopyrightText: KB Sriram +# +# SPDX-License-Identifier: MIT + +""" +Tests out +""" + +import pytest +from pytest_helpers import assert_assembles_to, assert_assembly_fails + + +@pytest.mark.parametrize( + "destination,expected", + [ + ("pins", 0b000), + ("x", 0b001), + ("y", 0b010), + ("null", 0b011), + ("pindirs", 0b100), + ("pc", 0b101), + ("isr", 0b110), + ("exec", 0b111), + ], +) +def test_out_destinations(destination: str, expected: int) -> None: + # delay dst bitcount + encoding = 0b011_00000_000_10001 + # add in the expected destination + encoding |= expected << 5 + assert_assembles_to(f"out {destination}, 17", [encoding]) + + +@pytest.mark.parametrize("delay", [0, 1, 9, 17, 31]) +def test_out_delay(delay: int) -> None: + # delay dst bitcount + encoding = 0b011_00000_000_10001 + # add in the expected delay + encoding |= delay << 8 + assert_assembles_to(f"out pins, 17 [{delay}]", [encoding]) + + +@pytest.mark.parametrize("bitcount", [1, 9, 17, 32]) +def test_out_bitcount(bitcount: int) -> None: + # delay dst bitcount + encoding = 0b011_00000_000_00000 + # add in the expected bitcount. Note that + # 32 should be encoded as 0, which we do by + # masking the bitcount with 0x1f + encoding |= bitcount & 0x1F + assert_assembles_to(f"out pins, {bitcount}", [encoding]) + + +def test_out_delay_with_sideset() -> None: + source = [ + ".side_set 2", + "out pins 17 side 2 [5]", + ] + assert_assembles_to("\n".join(source), [0b011_10_101_000_10001]) + + +def test_out_bad_destination(): + assert_assembly_fails( + "out bad, 17", match="Invalid out destination 'bad'", errtype=ValueError + ) + + +def test_out_bad_bitcount(): + assert_assembly_fails( + "out pins, 0", match="Count out of range", errtype=RuntimeError + )