Chapter 6 code

This commit is contained in:
Danny Staple
2022-01-28 21:10:14 +00:00
parent fd4b0cb544
commit 881355daaa
23 changed files with 723 additions and 33 deletions
+2 -2
View File
@@ -19,7 +19,7 @@ sm = rp2pio.StateMachine(
print("real frequency", sm.frequency) print("real frequency", sm.frequency)
while True: while True:
sm.write(bytes((1,))) sm.write(bytes([1]))
time.sleep(0.5) time.sleep(0.5)
sm.write(bytes((0,))) sm.write(bytes([0]))
time.sleep(0.5) time.sleep(0.5)
@@ -1,8 +1,10 @@
"""Send this code, run and watch the repl. """Send this code, run and watch the repl.
Then turn the wheel slowly to see the change""" Then turn the wheel slowly to see the change"""
import time
import board import board
import rp2pio import rp2pio
import adafruit_pioasm import adafruit_pioasm
import array
pio_input = """ pio_input = """
.program pio_input .program pio_input
@@ -12,17 +14,17 @@ pio_input = """
assembled = adafruit_pioasm.assemble(pio_input) assembled = adafruit_pioasm.assemble(pio_input)
## set up a statemachine
sm = rp2pio.StateMachine( sm = rp2pio.StateMachine(
assembled, assembled,
frequency=2000, frequency=2000,
first_in_pin=board.GP20 first_in_pin=board.GP20
) )
buffer = bytearray(1) # an array of bytes to read into - we are just asking for a byte buffer = array.array('I', [0])
while True: while True:
# read data from the fifo # read data from the fifo
data = sm.readinto(buffer) sm.readinto(buffer)
# print it. # print it.
print("{:08b}".format(buffer[0])) print(f"{buffer[0]:032b}")
time.sleep(0.1)
@@ -3,6 +3,7 @@ Then turn the wheel slowly to see the change"""
import board import board
import rp2pio import rp2pio
import adafruit_pioasm import adafruit_pioasm
import array
pio_input = """ pio_input = """
.program pio_input .program pio_input
@@ -24,6 +25,6 @@ buffer = bytearray(1) # an array of bytes to read into - we are just asking for
while True: while True:
# read data from the fifo # read data from the fifo
data = sm.readinto(buffer) sm.readinto(buffer)
# print it. # print it.
print("{:08b}".format(buffer[0])) print("{:08b}".format(buffer[0]))
+44
View File
@@ -0,0 +1,44 @@
"""Sometimes, you need to debug a register.
ISR is a bit special - when you push, you destroy it's content -
you'll need to restore this. If you remove the mov from x,
it is set to 0s.
It'll cost a few instructions to do."""
import rp2pio
import adafruit_pioasm
import array
program = """
.program debug_register
set y, 21 ; use y to set ISR
mov isr, y
; debug isr
mov x, isr ; preserve isr - pushing destroys it
push noblock
mov isr, x ; restore isr
; done debug
; debug isr
mov x, isr ; preserve isr - pushing destroys it
push noblock
mov isr, x ; restore isr
; done debug
"""
assembled = adafruit_pioasm.assemble(program)
## set up a statemachine
sm = rp2pio.StateMachine(
assembled,
frequency=2000,
)
buffer = array.array('I', [0])
# read the data
sm.readinto(buffer)
print("first push: {0} 0b{0:08b} 0x{0:x}".format(buffer[0]))
sm.readinto(buffer)
print("second: {0} 0b{0:08b} 0x{0:x}".format(buffer[0]))
+43
View File
@@ -0,0 +1,43 @@
"""Sometimes we want to extract a specific bit for
comparison or testing"""
"""Shifting a register."""
import rp2pio
import adafruit_pioasm
import array
# extracting bit 2
bit_to_extract = 30
program = f"""
.program extract_bit
pull block
; print initial state
mov isr, osr
push noblock ; and use PUSH to put it on the receive FIFO
; extract - by shifting
in osr, {bit_to_extract} ; get n bits
in null, 31 ; keep only 1 bit
push noblock
"""
assembled = adafruit_pioasm.assemble(program)
## set up a statemachine
sm = rp2pio.StateMachine(
assembled,
frequency=2000,
)
buffer = array.array('I', [0])
sm.write(array.array('I', [0b01101000_00000000_00000000_00000000]))
# read the data
sm.readinto(buffer)
print("Initial Y: {0} 0b{0:032b} 0x{0:x}".format(buffer[0]))
sm.readinto(buffer)
print("Y bit extracted: {0} 0b{0:032b} 0x{0:x}".format(buffer[0]))
+129
View File
@@ -0,0 +1,129 @@
"""Sometimes we want to extract a specific bit for
comparison or testing"""
"""Shifting a register."""
import rp2pio
import adafruit_pioasm
import array
def scenario(test_data, bit_to_extract, expected):
program = f"""
.program extract_bit
set y, {test_data} ; set a value in y
; extract - by shifting
in null, 32 ; clear the isr
in y, {bit_to_extract + 1} ; get n bits
; debug isr
mov x, isr ; preserve isr - pushing destroys it
push noblock
mov isr, x ; restore isr
; done debug
in null, 31 ; Shift off all but last bit (leaving it)
; debug isr
mov x, isr ; preserve isr - pushing destroys it
push noblock
mov isr, x ; restore isr
; done debug
mov y, isr ; reverse the isr back into y
; send y to fifo
mov isr, y
push noblock ; and use PUSH to put it on the receive FIFO
"""
assembled = adafruit_pioasm.assemble(program)
## set up a statemachine
with rp2pio.StateMachine(
assembled,
frequency=2000,
) as sm:
buffer = array.array('I', [0])
print("source bits: {0} 0b{0:032b} 0x{0:x}".format(test_data))
sm.readinto(buffer)
print("isr mid: {0} 0b{0:032b} 0x{0:x}".format(buffer[0]))
sm.readinto(buffer)
print("isr after shift off: {0} 0b{0:032b} 0x{0:x}".format(buffer[0]))
sm.readinto(buffer)
print("Y bit extracted: {0} 0b{0:032b} 0x{0:x}".format(buffer[0]))
if buffer[0] != expected:
print("Didn't get what I expected")
print("Y bit expected: {0} 0b{0:032b} 0x{0:x}".format(expected))
print("")
def pull_scenario(test_data, bit_to_extract, expected):
program = f"""
.program extract_bit_pull
pull block ; pull data
mov y, osr
; extract - by shifting
in null, 32 ; clear the isr
in y, {bit_to_extract + 1} ; get n bits
; debug isr
mov x, isr ; preserve isr - pushing destroys it
push noblock
mov isr, x ; restore isr
; done debug
in null, 31 ; Shift off all but last bit (leaving it)
; debug isr
mov x, isr ; preserve isr - pushing destroys it
push noblock
mov isr, x ; restore isr
; done debug
mov y, isr ; reverse the isr back into y
; send y to fifo
mov isr, y
push noblock ; and use PUSH to put it on the receive FIFO
"""
assembled = adafruit_pioasm.assemble(program)
## set up a statemachine
with rp2pio.StateMachine(
assembled,
frequency=2000,
) as sm:
sm.write(array.array('I', [test_data]))
buffer = array.array('I', [0])
print("source bits: {0} 0b{0:032b} 0x{0:x}".format(test_data))
sm.readinto(buffer)
print("isr mid: {0} 0b{0:032b} 0x{0:x}".format(buffer[0]))
sm.readinto(buffer)
print("isr after shift off: {0} 0b{0:032b} 0x{0:x}".format(buffer[0]))
sm.readinto(buffer)
print("Y bit extracted: {0} 0b{0:032b} 0x{0:x}".format(buffer[0]))
if buffer[0] != expected:
print("Didn't get what I expected")
print("Y bit expected: {0} 0b{0:032b} 0x{0:x}".format(expected))
print("")
scenario(0b101, 1, 0)
scenario(0b110, 1, 1)
scenario(0b010, 1, 1)
scenario(0b100, 2, 1)
scenario(0b011, 2, 0)
scenario(0b1011, 3, 1)
scenario(0b1010, 3, 1)
scenario(0b1000, 3, 1)
scenario(0b0111, 3, 0)
# bit I want
# v
pull_scenario(0b10101000_00000000_00000000_00000000, 29, 1)
pull_scenario(0b11011000_00000000_00000000_00000000, 29, 0)
# v
pull_scenario(0b01011000_00000000_00000000_00000000, 30, 1)
pull_scenario(0b10111000_00000000_00000000_00000000, 30, 0)
# v
pull_scenario(0b10111000_00000000_00000000_00000000, 31, 1)
pull_scenario(0b01111000_00000000_00000000_00000000, 31, 0)
+37
View File
@@ -0,0 +1,37 @@
"""We can invert the bits of a register."""
import rp2pio
import adafruit_pioasm
import array
program = """
.program invert_register
set y, 21 ; set a value in y
; send it to be printed
mov isr, y
push noblock ; and use PUSH to put it on the receive FIFO
; invert
mov isr, ~ y ; copy and reversed the registe into the ISR
; send it to be printed
push noblock ; and use PUSH to put it on the receive FIFO
"""
assembled = adafruit_pioasm.assemble(program)
## set up a statemachine
sm = rp2pio.StateMachine(
assembled,
frequency=2000,
)
buffer = array.array('i', [0])
# read the data
sm.readinto(buffer)
print("{0} 0b{0:032b} 0x{0:x}".format(buffer[0]))
# read the data
sm.readinto(buffer)
print("{0} 0b{0:032b} 0x{0:x}".format(buffer[0]))
+37
View File
@@ -0,0 +1,37 @@
"""Count down"""
import rp2pio
import adafruit_pioasm
import array
program = """
.program counting_down
set y, 21 ; set a value in y
; now send it to be printed
mov isr, y
push noblock ; and use PUSH to put it on the receive FIFO
jmp y--, fake ; subtract from it
fake:
; now send it to be printed
mov isr, y
push noblock ; and use PUSH to put it on the receive FIFO
"""
assembled = adafruit_pioasm.assemble(program)
## set up a statemachine
sm = rp2pio.StateMachine(
assembled,
frequency=2000,
)
buffer = array.array('I', [0])
# read the data
sm.readinto(buffer)
print("Before {0} 0b{0:08b} 0x{0:x}".format(buffer[0]))
# read the data
sm.readinto(buffer)
print("After {0} 0b{0:08b} 0x{0:x}".format(buffer[0]))
+39
View File
@@ -0,0 +1,39 @@
"""Count down"""
import rp2pio
import adafruit_pioasm
import array
program = """
.program counting_up
set y, 21 ; set a value in y
; now send it to be printed
mov isr, y
push noblock ; and use PUSH to put it on the receive FIFO
; Add 1
mov y, ~ y ; invert it
jmp y--, fake ; subtract from it
fake:
mov isr, ~ y
push noblock ; and use PUSH to put it on the receive FIFO
"""
assembled = adafruit_pioasm.assemble(program)
## set up a statemachine
sm = rp2pio.StateMachine(
assembled,
frequency=2000,
)
buffer = array.array('I', [0])
# read the data
sm.readinto(buffer)
print("Before {0} 0b{0:08b} 0x{0:x}".format(buffer[0]))
# read the data
sm.readinto(buffer)
print("After {0} 0b{0:08b} 0x{0:x}".format(buffer[0]))
@@ -0,0 +1,26 @@
"""Sometimes, you need to debug a register.
Note - ISR content is destroyed.
It'll cost a few instructions to do."""
import rp2pio
import adafruit_pioasm
import array
program = """
.program debug_register
set y, 21 ; set a value in y
; now send it to be printed
mov isr, y ; copy the register you need to dump into the ISR
push noblock ; and use PUSH to put it on the receive FIFO
"""
assembled = adafruit_pioasm.assemble(program)
## set up a statemachine
sm = rp2pio.StateMachine(assembled, frequency=2000)
buffer = array.array('I', [0])
# read the data
sm.readinto(buffer)
print("{0} 0b{0:08b}".format(buffer[0]))
+37
View File
@@ -0,0 +1,37 @@
"""We can reverse the content of a register."""
import rp2pio
import adafruit_pioasm
import array
program = """
.program reverse_register
set y, 21 ; set a value in y
; send it to be printed
mov isr, y
push noblock ; and use PUSH to put it on the receive FIFO
; reverse it
mov isr, :: y ; copy and reversed the register into the ISR
; print it
push noblock ; and use PUSH to put it on the receive FIFO
"""
assembled = adafruit_pioasm.assemble(program)
## set up a statemachine
sm = rp2pio.StateMachine(
assembled,
frequency=2000,
)
buffer = array.array('I', [0])
# read the data
sm.readinto(buffer)
print("{0} 0b{0:032b} 0x{0:x}".format(buffer[0]))
# read the data
sm.readinto(buffer)
print("{0} 0b{0:032b} 0x{0:x}".format(buffer[0]))
+40
View File
@@ -0,0 +1,40 @@
"""Shift and reverse"""
import rp2pio
import adafruit_pioasm
import array
program = """
.program debug_register
set y, 2 ; set a value in y
; send it to be printed
mov isr, y
push noblock ; and use PUSH to put it on the receive FIFO
; shift and reverse
in y, 1 ; get bits
mov isr, :: isr ; reverse it
; print again
push noblock ; and use PUSH to put it on the receive FIFO
"""
assembled = adafruit_pioasm.assemble(program)
## set up a statemachine
sm = rp2pio.StateMachine(
assembled,
frequency=2000,
)
buffer = array.array('I', [0])
# read the data
sm.readinto(buffer)
print("{0} 0b{0:032b} 0x{0:x}".format(buffer[0]))
# read the data
sm.readinto(buffer)
print("{0} 0b{0:032b} 0x{0:x}".format(buffer[0]))
+49
View File
@@ -0,0 +1,49 @@
"""Shifting a register.
Default shift direction is in from the left.
Space is made for the new value, and n bits from the source are
shifted in.
"""
import rp2pio
import adafruit_pioasm
import array
program = f"""
.program debug_register
set y, {0b10011} ; set a value in y
; send it to be printed
mov isr, y
push noblock ; and use PUSH to put it on the receive FIFO
; shift pts
in null, 32 ; clear the isr
in y,3 ; get n bits from y
; now send it to be printed
push noblock ; and use PUSH to put it on the receive FIFO
; show state of y
mov isr, y
push noblock
"""
assembled = adafruit_pioasm.assemble(program)
## set up a statemachine
sm = rp2pio.StateMachine(
assembled,
frequency=2000,
)
buffer = array.array('I', [0])
# read the data
sm.readinto(buffer)
print("Before shift: {0} 0b{0:032b} 0x{0:x}".format(buffer[0]))
sm.readinto(buffer)
print("ISR shifted: {0} 0b{0:032b} 0x{0:x}".format(buffer[0]))
sm.readinto(buffer)
print("Y state: {0} 0b{0:032b} 0x{0:x}".format(buffer[0]))
@@ -3,13 +3,14 @@ Then turn the wheel slowly to see the change"""
import board import board
import rp2pio import rp2pio
import adafruit_pioasm import adafruit_pioasm
import array
pio_input = """ program = """
.program pio_input .program pio_input
set y, 0 ; clear y set y, 0 ; clear y
read: read:
mov x, y ; store old Y in x mov x, y ; store old Y in x
in null, 31 ; Clear ISR in null, 32 ; Clear ISR
in pins, 2 ; read in two pins (into ISR) in pins, 2 ; read in two pins (into ISR)
mov y, isr ; store ISR in y mov y, isr ; store ISR in y
jmp x!=y different ; Jump if its different jmp x!=y different ; Jump if its different
@@ -20,22 +21,18 @@ different:
jmp read ; loop back jmp read ; loop back
""" """
assembled = adafruit_pioasm.assemble(pio_input) assembled = adafruit_pioasm.assemble(program)
## set up a statemachine ## set up a statemachine
sm = rp2pio.StateMachine( sm = rp2pio.StateMachine(
assembled, assembled,
frequency=2000, frequency=20000,
first_in_pin=board.GP20, first_in_pin=board.GP20,
in_pin_count=2 in_pin_count=2
) )
buffer = bytearray(1) # an array of bytes to read into - we are just asking for a byte (are we though? It might be 4 bytes) buffer = array.array('I', [0])
while True: while True:
# read data from the fifo sm.readinto(buffer)
# print (sm.in_waiting) print("{:032b}".format(buffer[0]))
if sm.in_waiting:
data = sm.readinto(buffer)
# print it.
print("{:08b}".format(buffer[0]))
@@ -3,8 +3,9 @@ Then turn the wheel slowly to see the change"""
import board import board
import rp2pio import rp2pio
import adafruit_pioasm import adafruit_pioasm
import array
pio_input = """ program = """
.program pio_input .program pio_input
set y, 0 ; clear y set y, 0 ; clear y
read: read:
@@ -20,7 +21,7 @@ different:
jmp read ; loop back jmp read ; loop back
""" """
assembled = adafruit_pioasm.assemble(pio_input) assembled = adafruit_pioasm.assemble(program)
## set up a statemachine ## set up a statemachine
left_enc = rp2pio.StateMachine( left_enc = rp2pio.StateMachine(
@@ -37,7 +38,7 @@ right_enc = rp2pio.StateMachine(
in_pin_count=2 in_pin_count=2
) )
buffer = bytearray(1) # an array of bytes to read into - we are just asking for a byte (are we though? It might be 4 bytes) buffer = array.array('I', [0])
left_data = 0 left_data = 0
right_data = 0 right_data = 0
@@ -0,0 +1,93 @@
"""Send this code, run and watch the repl.
Then turn the wheel slowly to see the change"""
import board
import rp2pio
import adafruit_pioasm
import array
program = """
; use the osr for count
; input pins c1 c2
set y, 0 ; clear y
mov osr, y ; and clear osr
read:
; x will be the old value
; y the new values
mov x, y ; store old Y in x
in null, 32 ; Clear ISR - using y
in pins, 2 ; read two pins into y
mov y, isr
jmp x!=y, different ; Jump if its different
jmp read ; otherwise loop back to read
different:
; x has old value, y has new.
; extract the upper bit of X.
in x, 31 ; get bit 31 - old p1 (remember which direction it came in)
in null, 31 ; keep only 1 bit
mov x, isr ; put this back in x
jmp !x, c1_old_zero
c1_old_not_zero:
jmp pin, count_up
jmp count_down
c1_old_zero:
jmp pin, count_down
; fall through
count_up:
; for a clockwise move - we'll add 1 by inverting
mov x, ~ osr ; store inverted OSR on x
jmp x--, fake ; use jump to take off 1
fake:
mov x, ~ x ; invert back
jmp send
count_down:
; for a clockwise move, just take one off
mov x, osr ; store osr in x
jmp x--, send ; dec and send
send:
; send x.
mov isr, x ; send it
push noblock ; put ISR into input FIFO
mov osr, x ; put X back in OSR
jmp read ; loop back
"""
assembled = adafruit_pioasm.assemble(program)
## set up a statemachine
left_enc = rp2pio.StateMachine(
assembled,
frequency=0,
first_in_pin=board.GP20,
jmp_pin=board.GP21,
in_pin_count=2
)
right_enc = rp2pio.StateMachine(
assembled,
frequency=0,
first_in_pin=board.GP26,
jmp_pin=board.GP27,
in_pin_count=2
)
buffer = array.array('i', [0])
left_data = 0
right_data = 0
while True:
# read data from the fifo
if left_enc.in_waiting:
left_enc.readinto(buffer)
left_data = buffer[0]
# print it.
print(left_data, right_data)
if right_enc.in_waiting:
right_enc.readinto(buffer)
right_data = buffer[0]
# print it.
print(left_data, right_data)
+24
View File
@@ -0,0 +1,24 @@
"""Copy the adafruit_hid folder into CIRCUITPY, run this,
and move the wheels on the robot. Why? Why not."""
import robot
import usb_hid
from adafruit_hid.mouse import Mouse
print("Setting up Hid")
mouse = Mouse(usb_hid.devices)
last_x = 0
last_y = 0
print("Entering main loop")
while True:
x = robot.left_encoder.read()
y = robot.right_encoder.read()
x_diff = x - last_x
y_diff = y - last_y
last_x = x
last_y = y
mouse.move(x=x_diff, y=y_diff)
+9
View File
@@ -0,0 +1,9 @@
import time
import robot
robot.set_left(0.8)
robot.set_right(0.8)
time.sleep(1)
robot.stop()
print(robot.left_encoder.read(), robot.right_encoder.read())
+77
View File
@@ -0,0 +1,77 @@
import rp2pio
import adafruit_pioasm
import array
program = """
; use the osr for count
; input pins c1 c2
set y, 0 ; clear y
mov osr, y ; and clear osr
read:
; x will be the old value
; y the new values
mov x, y ; store old Y in x
in null, 32 ; Clear ISR - using y
in pins, 2 ; read two pins into y
mov y, isr
jmp x!=y, different ; Jump if its different
jmp read ; otherwise loop back to read
different:
; x has old value, y has new.
; extract the upper bit of X.
in x, 31 ; get bit 31 - old p1 (remember which direction it came in)
in null, 31 ; keep only 1 bit
mov x, isr ; put this back in x
jmp !x, c1_old_zero
c1_old_not_zero:
jmp pin, count_up
jmp count_down
c1_old_zero:
jmp pin, count_down
; fall through
count_up:
; for a clockwise move - we'll add 1 by inverting
mov x, ~ osr ; store inverted OSR on x
jmp x--, fake ; use jump to take off 1
fake:
mov x, ~ x ; invert back
jmp send
count_down:
; for a clockwise move, just take one off
mov x, osr ; store osr in x
jmp x--, send ; dec and send
send:
; send x.
mov isr, x ; send it
push noblock ; put ISR into input FIFO
mov osr, x ; put X back in OSR
jmp read ; loop back
"""
assembled = adafruit_pioasm.assemble(program)
class QuadratureEncoder:
def __init__(self, first_pin, second_pin, reversed=False):
"""Encoder with 2 pins. Must use sequential pins on the board"""
self.sm = rp2pio.StateMachine(
assembled,
frequency=0,
first_in_pin=first_pin,
jmp_pin=second_pin,
in_pin_count=2
)
self.reversed = reversed
self._buffer = array.array('i', [0])
def read(self):
while self.sm.in_waiting:
self.sm.readinto(self._buffer)
if self.reversed:
return -self._buffer[0]
else:
return self._buffer[0]
+4
View File
@@ -1,5 +1,6 @@
import board import board
import pwmio import pwmio
import pio_encoder
motor_A1 = pwmio.PWMOut(board.GP17) motor_A1 = pwmio.PWMOut(board.GP17)
motor_A2 = pwmio.PWMOut(board.GP16) motor_A2 = pwmio.PWMOut(board.GP16)
@@ -9,6 +10,9 @@ motor_B2 = pwmio.PWMOut(board.GP19)
right_motor = motor_A1, motor_A2 right_motor = motor_A1, motor_A2
left_motor = motor_B1, motor_B2 left_motor = motor_B1, motor_B2
right_encoder = pio_encoder.QuadratureEncoder(board.GP20, board.GP21, reversed=True)
left_encoder = pio_encoder.QuadratureEncoder(board.GP26, board.GP27)
def stop(): def stop():
motor_A1.duty_cycle = 0 motor_A1.duty_cycle = 0
motor_A2.duty_cycle = 0 motor_A2.duty_cycle = 0
Binary file not shown.
+13
View File
@@ -0,0 +1,13 @@
import time
import robot
robot.set_left(0.8)
robot.set_right(0.8)
target = 4000
while robot.left_encoder.read() < target or robot.right_encoder.read() < target:
if robot.left_encoder.read() >= target:
robot.set_left(0)
if robot.right_encoder.read() >= target:
robot.set_right(0)
print(robot.left_encoder.read(), robot.right_encoder.read())
-12
View File
@@ -1,12 +0,0 @@
import time
import board
import digitalio
pin = digitalio.DigitalInOut(board.GP4)
pin.direction = digitalio.Direction.OUTPUT
while True:
pin.value = True
time.sleep(0.01)
pin.value = False
time.sleep(0.01)