-
-
Save n13i/3256c9269badef6021778b8d4a66a617 to your computer and use it in GitHub Desktop.
Communicate with N64 Controller using Raspberry Pi Pico with MicroPython
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from rp2 import PIO, StateMachine, asm_pio | |
from machine import Pin | |
import time | |
dataPin = Pin(0) # GP0 | |
@asm_pio(out_init=PIO.OUT_HIGH, set_init=PIO.OUT_HIGH, sideset_init=PIO.OUT_HIGH, | |
out_shiftdir=PIO.SHIFT_LEFT, pull_thresh=32, autopull=False, | |
in_shiftdir=PIO.SHIFT_LEFT, push_thresh=32, autopush=False) | |
def joybus_write_read(): | |
# prepare for detect Controller Stop Bit | |
set(y, 0b1111) | |
# write data ------------------------ | |
set(pindirs, 1).side(1) # 1:output | |
# 4 cycles loop | |
wrap_target() | |
pull(ifempty) | |
# to send Console Stop Bit, put 0xffffffff to osr | |
# normally osr has at least one 0 bit, so put(0xffffffff) to osr explicitly to stop | |
mov(x, invert(osr)) | |
jmp(not_x, "send_stopbit") | |
out(pins, 1) # shift out from OSR | |
wrap() | |
# ------------------------ | |
label("send_stopbit") | |
set(pins, 0)[3] # Console Stop Bit (1us LOW/>2us HIGH) | |
set(pindirs, 0) # 0:input | |
# if no controller connected, pin goes LOW here | |
# wait for falling edge | |
wait(0, pin, 0) | |
# ------------------------ | |
# 4 cycles loop | |
label("readloop") | |
in_(pins, 1) # shift in | |
push(iffull) | |
# check Controller Stop Bit (2us LOW/>2us HIGH) | |
mov(x, isr) | |
jmp(x_not_y, "readloop") | |
label("end") | |
jmp("end") | |
def get_byte(in_bits): | |
# convert from lower 4 bits | |
# ex) 0001 0001 0001 0001 0001 0111 0001 0111 | |
# (0) (0) (0) (0) (0) (1) (0) (1) | |
# -> 0x05 = 0b00000101 | |
ib = in_bits | |
r = 0 | |
for i in range(8): | |
r = r >> 1 | |
if (ib & 0x0000000f) == 0b0111: # One | |
r = r | 0b10000000 | |
ib = ib >> 4 | |
print(f'>> {r:02x}: {in_bits:032b}') | |
return r | |
def get_bits(out_byte): | |
# convert from LSB | |
# ex) 0x12 = 0b00010010 | |
# -> 0001 0001 0001 0111 0001 0001 0111 0001 | |
ob = out_byte | |
r = 0 | |
for i in range(8): | |
r = r << 4 | |
if (ob & 0x80) == 0x80: | |
r = r | 0b0111 # One | |
else: | |
r = r | 0b0001 # Zero | |
ob = ob << 1 | |
print(f'<< {out_byte:02x}: {r:032b}') | |
return r | |
def send_bits(sm, bits): | |
array = [] | |
for a in bits: | |
array.append(get_bits(a)) | |
array.append(0xffffffff) # Stop | |
for b in array: | |
sm.put(b) | |
def recv_bits(sm): | |
while sm.rx_fifo() > 0: | |
v = sm.get() | |
get_byte(v) | |
# 4MHz (0.25us/cycle) | |
sm = StateMachine(0, joybus_write_read, freq=4000000, set_base=dataPin, | |
sideset_base=dataPin, out_base=dataPin, in_base=dataPin) | |
sm.active(1) | |
while True: | |
print("send") | |
send_bits(sm, [0x01]) | |
print("recv") | |
recv_bits(sm) | |
time.sleep_ms(100) | |
sm.restart() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment