diff --git a/adafruit_pioasm.py b/adafruit_pioasm.py index 22bf47b..e225a7d 100644 --- a/adafruit_pioasm.py +++ b/adafruit_pioasm.py @@ -31,7 +31,7 @@ def assemble(text_program): """Converts pioasm text to encoded instruction bytes""" - # pylint: disable=too-many-branches,too-many-statements + # pylint: disable=too-many-branches,too-many-statements,too-many-locals assembled = [] program_name = None labels = {} @@ -55,7 +55,10 @@ def assemble(text_program): elif line.startswith(".side_set"): sideset_count = int(line.split()[1]) elif line.endswith(":"): - labels[line[:-1]] = len(instructions) + label = line[:-1] + if label in labels: + raise SyntaxError(f"Duplicate label {repr(label)}") + labels[label] = len(instructions) elif line: # Only add as an instruction if the line isn't empty instructions.append(line) @@ -85,10 +88,13 @@ def assemble(text_program): elif instruction[0] == "jmp": # instr delay cnd addr assembled.append(0b000_00000_000_00000) - if instruction[-1] in labels: - assembled[-1] |= labels[instruction[-1]] + target = instruction[-1] + if target[:1] in "0123456789": + assembled[-1] |= int(target) + elif instruction[-1] in labels: + assembled[-1] |= labels[target] else: - assembled[-1] |= int(instruction[-1]) + raise SyntaxError(f"Invalid jmp target {repr(target)}") if len(instruction) > 2: assembled[-1] |= CONDITIONS.index(instruction[1]) << 5 diff --git a/examples/getting-started/README.md b/examples/getting-started/README.md new file mode 100644 index 0000000..639ed26 --- /dev/null +++ b/examples/getting-started/README.md @@ -0,0 +1,7 @@ + + +These examples are adapted from [Getting started with MicroPython on the Raspberry Pi Pico](https://www.adafruit.com/product/4898). You can also get an [electonic copy](https://hackspace.raspberrypi.org/books/micropython-pico/). PIO is covered in Appendix C. diff --git a/examples/getting-started/led_brightness.py b/examples/getting-started/led_brightness.py new file mode 100644 index 0000000..71ba925 --- /dev/null +++ b/examples/getting-started/led_brightness.py @@ -0,0 +1,49 @@ +# SPDX-FileCopyrightText: 2021 Jeff Epler, written for Adafruit Industries +# +# SPDX-License-Identifier: MIT +# +# Adapted from the an example in Appendix C of RPi_PiPico_Digital_v10.pdf + +import time +import board +import rp2pio +import adafruit_pioasm + +led_quarter_brightness = adafruit_pioasm.assemble( + """ + set pins, 0 [2] + set pins, 1 +""" +) + +led_half_brightness = adafruit_pioasm.assemble( + """ + set pins, 0 + set pins, 1 +""" +) + +led_full_brightness = adafruit_pioasm.assemble( + """ + set pins, 1 +""" +) + +while True: + sm = rp2pio.StateMachine( + led_quarter_brightness, frequency=10000, first_set_pin=board.LED + ) + time.sleep(1) + sm.deinit() + + sm = rp2pio.StateMachine( + led_half_brightness, frequency=10000, first_set_pin=board.LED + ) + time.sleep(1) + sm.deinit() + + sm = rp2pio.StateMachine( + led_full_brightness, frequency=10000, first_set_pin=board.LED + ) + time.sleep(1) + sm.deinit() diff --git a/examples/pico-examples/README.md b/examples/pico-examples/README.md new file mode 100644 index 0000000..e6f42e1 --- /dev/null +++ b/examples/pico-examples/README.md @@ -0,0 +1,7 @@ + + +These examples are adapted from the pio folder of the [Raspberry Pi Pico SDK Examples](https://github.com/raspberrypi/pico-examples). diff --git a/examples/pico-examples/blink.py b/examples/pico-examples/blink.py new file mode 100644 index 0000000..3d2fc97 --- /dev/null +++ b/examples/pico-examples/blink.py @@ -0,0 +1,43 @@ +# SPDX-FileCopyrightText: 2021 Jeff Epler, written for Adafruit Industries +# +# SPDX-License-Identifier: MIT +# +# Adapted from the example https://github.com/raspberrypi/pico-examples/tree/master/pio/pio_blink + +import array +import time +import board +import rp2pio +import adafruit_pioasm + +blink = adafruit_pioasm.assemble( + """ +.program blink + pull block ; These two instructions take the blink duration + out y, 32 ; and store it in y +forever: + mov x, y + set pins, 1 ; Turn LED on +lp1: + jmp x-- lp1 ; Delay for (x + 1) cycles, x is a 32 bit number + mov x, y + set pins, 0 ; Turn LED off +lp2: + jmp x-- lp2 ; Delay for the same number of cycles again + jmp forever ; Blink forever! +""" +) + + +while True: + for freq in [5, 8, 30]: + with rp2pio.StateMachine( + blink, + frequency=125_000_000, + first_set_pin=board.LED, + wait_for_txstall=False, + ) as sm: + data = array.array("I", [sm.frequency // freq]) + sm.write(data) + time.sleep(3) + time.sleep(0.5) diff --git a/examples/pico-examples/hello.py b/examples/pico-examples/hello.py new file mode 100644 index 0000000..ade87ad --- /dev/null +++ b/examples/pico-examples/hello.py @@ -0,0 +1,37 @@ +# SPDX-FileCopyrightText: 2021 Jeff Epler, written for Adafruit Industries +# +# SPDX-License-Identifier: MIT +# +# Adapted from the example https://github.com/raspberrypi/pico-examples/tree/master/pio/hello_pio + +import time +import board +import rp2pio +import adafruit_pioasm + +hello = """ +.program hello +loop: + pull + out pins, 1 +; This program uses a 'jmp' at the end to follow the example. However, +; in a many cases (including this one!) there is no jmp needed at the end +; and the default "wrap" behavior will automatically return to the "pull" +; instruction at the beginning. + jmp loop +""" + +assembled = adafruit_pioasm.assemble(hello) + +sm = rp2pio.StateMachine( + assembled, + frequency=2000, + first_out_pin=board.LED, +) +print("real frequency", sm.frequency) + +while True: + sm.write(bytes((1,))) + time.sleep(0.5) + sm.write(bytes((0,))) + time.sleep(0.5)