Skip to content

Add sideset assembly support. #27

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 4 commits into from
Dec 26, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions adafruit_pioasm.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def assemble(text_program):
labels = {}
instructions = []
sideset_count = 0
sideset_enable = 0
for line in text_program.split("\n"):
line = line.strip()
if not line:
Expand All @@ -55,6 +56,7 @@ def assemble(text_program):
pass
elif line.startswith(".side_set"):
sideset_count = int(line.split()[1])
sideset_enable = 1 if "opt" in line else 0
elif line.endswith(":"):
label = line[:-1]
if label in labels:
Expand All @@ -64,7 +66,7 @@ def assemble(text_program):
# Only add as an instruction if the line isn't empty
instructions.append(line)

max_delay = 2 ** (5 - sideset_count) - 1
max_delay = 2 ** (5 - sideset_count - sideset_enable) - 1
assembled = []
for instruction in instructions:
# print(instruction)
Expand All @@ -76,10 +78,13 @@ def assemble(text_program):
raise RuntimeError("Delay too long:", delay)
instruction.pop()
if len(instruction) > 1 and instruction[-2] == "side":
if sideset_count == 0:
raise RuntimeError("No side_set count set")
sideset_value = int(instruction[-1])
if sideset_value > 2 ** sideset_count:
raise RuntimeError("Sideset value too large")
delay |= sideset_value << (5 - sideset_count)
delay |= sideset_value << (5 - sideset_count - sideset_enable)
delay |= sideset_enable << 4
instruction.pop()
instruction.pop()

Expand Down Expand Up @@ -186,6 +191,6 @@ def assemble(text_program):
else:
raise RuntimeError("Unknown instruction:" + instruction[0])
assembled[-1] |= delay << 8
# print(hex(assembled[-1]))
# print(bin(assembled[-1]))

return array.array("H", assembled)
53 changes: 53 additions & 0 deletions examples/txuart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# SPDX-FileCopyrightText: 2021 Jeff Epler, written for Adafruit Industries
#
# SPDX-License-Identifier: MIT

import rp2pio
import adafruit_pioasm

code = adafruit_pioasm.assemble(
"""
.program uart_tx
.side_set 1 opt

; An 8n1 UART transmit program.
; OUT pin 0 and side-set pin 0 are both mapped to UART TX pin.

pull side 1 [7] ; Assert stop bit, or stall with line in idle state
set x, 7 side 0 [7] ; Preload bit counter, assert start bit for 8 clocks
bitloop: ; This loop will run 8 times (8n1 UART)
out pins, 1 ; Shift 1 bit from OSR to the first OUT pin
jmp x-- bitloop [6] ; Each loop iteration is 8 cycles.

"""
)


class TXUART:
def __init__(self, *, tx, baudrate=9600):
self.pio = rp2pio.StateMachine(
code,
first_out_pin=tx,
first_sideset_pin=tx,
frequency=8 * baudrate,
initial_sideset_pin_state=1,
initial_sideset_pin_direction=1,
initial_out_pin_state=1,
initial_out_pin_direction=1,
sideset_enable=True,
)

@property
def timeout(self):
return 0

@property
def baudrate(self):
return self.pio.frequency // 8

@baudrate.setter
def baudrate(self, frequency):
self.pio.frequency = frequency * 8

def write(self, buf):
return self.pio.write(buf)
7 changes: 7 additions & 0 deletions tests/testpioasm.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ def testNop(self):
self.assertAssemblesTo(".side_set 1\nnop side 1", [0b101_10000_010_00_010])
self.assertAssemblesTo(".side_set 1\nnop side 1 [1]", [0b101_10001_010_00_010])

def testSidesetOpt(self):
self.assertAssemblesTo(".side_set 1 opt\nnop side 1", [0b101_11000_010_00_010])
self.assertAssemblesTo(
".side_set 1 opt\nnop side 0 [1]", [0b101_10001_010_00_010]
)
self.assertAssemblesTo(".side_set 1 opt\nnop [1]", [0b101_00001_010_00_010])

def testJmp(self):
self.assertAssemblesTo("l:\njmp l", [0b000_00000_000_00000])
self.assertAssemblesTo("l:\njmp 7", [0b000_00000_000_00111])
Expand Down