Skip to content

Add some examples, improve the assembler #11

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 12 commits into from
Feb 25, 2021
16 changes: 11 additions & 5 deletions adafruit_pioasm.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {}
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Comment on lines +92 to +93
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check will only work for single digit targets but it could be up to 32. Instead, you could try and int(target) and then catch the error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not quite, but maybe the code is too clever as written. It looks whether the first character (if present) in target is a digit.

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
Expand Down
7 changes: 7 additions & 0 deletions examples/getting-started/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!--
SPDX-FileCopyrightText: 2020 Jeff Epler, written for Adafruit Industries

SPDX-License-Identifier: MIT
-->

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.
49 changes: 49 additions & 0 deletions examples/getting-started/led_brightness.py
Original file line number Diff line number Diff line change
@@ -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()
7 changes: 7 additions & 0 deletions examples/pico-examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!--
SPDX-FileCopyrightText: 2020 Jeff Epler, written for Adafruit Industries

SPDX-License-Identifier: MIT
-->

These examples are adapted from the pio folder of the [Raspberry Pi Pico SDK Examples](https://github.com/raspberrypi/pico-examples).
37 changes: 37 additions & 0 deletions examples/pico-examples/hello.py
Original file line number Diff line number Diff line change
@@ -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)