#-------------------------------------------------------
#  T́@PIOvO~O@\[Xꎮ (2021/6/13)
#-------------------------------------------------------


#--------------------------------------
# XgP  NOP߂svO
#--------------------------------------
import rp2

#----------------------------
# Xe[g}VpR[h̒`ƃAZu
#----------------------------
@rp2.asm_pio()                     # fR[^asm_pioݒ肷邱Ƃ
def nop_prog():                    # AZuiasm_piojĂяo
    nop()                          # NOP߂Ȃ\[XR[h
                                   # (⑫FNOP߂MOV߂őp܂)
#----------------------------

# Xe[g}V̐ݒƃIuWFNg
#  PIO[0]StateMachine[0]wAoCiR[hnop_progw
sm = rp2.StateMachine(0, nop_prog)

# Xe[g}V̋N
sm.active(1)

#--------------------------------------




#--------------------------------------
# XgQ  SET߂pLED_łvO
#--------------------------------------
import rp2
from machine import Pin

# Xe[g}VpR[h̒`ƃAZu
#----------------------------
@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
def blink_LED():
    set(pins, 1)   # SET Pin  <- H
    set(pins, 0)   # SET Pin  <- L
#----------------------------

# LEDpPin̐
led_pin = Pin(25, Pin.OUT)

# Xe[g}V̐ݒƃIuWFNg
# PIO_0StateMachine_0𗘗pA߂blink_LEDwANbN2000Hzw
sm = rp2.StateMachine(0, blink_LED, set_base=led_pin, freq=2000)

# Xe[g}V̋N
sm.active(1)

#------------------------------------------------




#--------------------------------------
# XgR MicroPython𗘗pLED ̓_𐧌䂷vO
#--------------------------------------
import utime
import rp2
from machine import Pin

# Xe[g}VpR[h̒`ƃAZu
#----------------------------
@rp2.asm_pio(out_init=rp2.PIO.OUT_LOW,out_shiftdir=rp2.PIO.SHIFT_RIGHT)
def control_LED():
    pull()          # FIFOOSRւ̃f[^ǂݍ
    out(pins, 1)    # OSR  Pinւ1bitf[^(Vtg͉E)
#----------------------------

# LEDpPin̐
led_pin = Pin(25, Pin.OUT)

# Xe[g}V̐ݒƃIuWFNg
# PIO[0]StateMachine[0]𗘗pA߂control_LEDw
sm = rp2.StateMachine(0, control_LED, out_base=led_pin)

# Xe[g}V̋N
sm.active(1)

# FIFOւ̏
while True:
    sm.put(1)  # LED_
    utime.sleep(1)
    sm.put(0)  # LED
    utime.sleep(1)
#----------------------------------------------------------


#--------------------------------------
# XgS@SW ON/OFF ԂPIO 擾vO
#           SWGP0ɐڑ(̃rԍ1)
#--------------------------------------
import rp2
from machine import Pin
#
# Xe[g}VpR[h̒`ƃAZu
#----------------------------
@rp2.asm_pio(in_shiftdir=rp2.PIO.SHIFT_LEFT)
def sw_status():
    in_(pins, 1)    # Pinf[^擾ISRɊi[ (Vtgw)
    push()          # ISR̒lRX FIFOɏ
#----------------------------

# SW͗pPinIuWFNg̐
sw_pin = Pin(0, Pin.IN, Pin.PULL_UP)                 # ͂ƂPin0IAPULL_UPݒ

# Xe[g}V̐ݒƃIuWFNg
sm = rp2.StateMachine(0, sw_status, in_base=sw_pin)  # Piñx[Xw

# Xe[g}V̋N
sm.active(1)

# PIO(RX FIFO)SWԂ擾A\[v
prev_val = None
while True:
    val = sm.get()             # SW̏ԂRX FIFO擾
    if val != prev_val:
        print(val,end="")
        prev_val = val
#------------------------------------------------



#--------------------------------------
# XgT@XCb`ꂽۂIRQ 𔭍s
#           R[obN֐ĂяoTv
#           SWGP0ɐڑ(̃rԍ1)
#--------------------------------------
import utime
import rp2
from machine import Pin

#R[obNp֐̒`(PIOIuWFNgɓo^O)
def intr(pio):
    print("InterruptHandler")
    flags = pio.irq().flags()           # IRQ tO擾
    print("{:04x}: ".format(flags),end="")
    if flags & rp2.PIO.IRQ_SM0:         # IRQtO̓(bittB[hł̔r)
        print("catch irq(0)")
    else:
        print("not irq(0)")
#
# Xe[g}VpR[h̒`ƃAZu
#----------------------------
@rp2.asm_pio(in_shiftdir=rp2.PIO.SHIFT_LEFT)
def sw_status():
    label("top")
    in_(pins, 1)          # PinSW̏Ԃ擾ISRɊi[ (SHIFT _LEFT)
    mov(x,isr)            # ISR̒lėpWX^X ɃRs[
    jmp(not_x,"trigger")  # if x == 0  then goto "trigger" 
    jmp("top")            #            else goto "top"
    label("trigger")
    irq(0)                # IRQtOF0w肵IRQ𔭐
    jmp("top")            # top̃xJMPi̍sĂ擪sɖ߂܂j
#----------------------------

# SW͗pPin̐
sw_pin = Pin(0, Pin.IN, Pin.PULL_UP)   # ͂ƂPin0IAPULL_UPݒ

# Xe[g}V̐ݒƃIuWFNg
# PIO[0]StateMachine[0]
sm = rp2.StateMachine(0, sw_status, in_base=sw_pin, freq=2000)

# PIO_0ɃR[obN֐(intr)o^
rp2.PIO(0).irq(intr)

# Xe[g}V̋N
sm.active(1)

# MicroPythonC[v
while True:
    utime.sleep(1)
    print("zzz...")
#------------------------------------------------




#--------------------------------------
# XgU@IRQ ɂXe[gE}V̎s𓯊Tv
#--------------------------------------
import rp2
import utime

# R[obN֐̒`
def hdlr0(arg):
    print("called Hander0")

def hdlr1(arg):
    print("called Hander1")

def hdlr2(arg):
    print("called Hander2")

# 
# Xe[g}VpR[h̒`ƃAZu
@rp2.asm_pio()
def timer1sec():
     #  (1 + 7) + ((30 + 1) + (30 + 1)) * 32 + (1 + 7) (= 2000)
     set(x, 31)              [7]  #  x <- 1f
     label("wait_loop")
     nop()                   [30]
     jmp(x_dec,"wait_loop")  [30]
     irq(4)                  [7]    # IRQtO4IRQ𔭍sij

@rp2.asm_pio()
def consumer():
     wait(1,irq,4)  # IRQtO41ɂȂ܂ő҂
     irq(2)         # IRGtO2IRQ𔭍s

@rp2.asm_pio()
def asm_nop():
     nop

# Xe[g}V̐ݒƃIuWFNg
# PIO[0]StateMachine[0]
sm0 = rp2.StateMachine(0, timer1sec, freq = 2000) 
sm0.irq(hdlr0)

# PIO[0]StateMachine[1]
sm1 = rp2.StateMachine(1, consumer, freq = 2000) 
sm1.irq(hdlr1)

# PIO[0]StateMachine[2]
sm2 = rp2.StateMachine(2,asm_nop, freq = 2000) 
sm2.irq(hdlr2) 

sm0.active(1)
sm1.active(1)
sm2.active(1)
utime.sleep(5)
sm0.active(0)
sm1.active(0)
sm2.active(0)
#--------------------------------------------------------------





#--------------------------------------
# XgV@PIO p[^EGR[_phCoiencoder_pio.pyj
#--------------------------------------
from rp2 import PIO
from rp2 import StateMachine
from rp2 import asm_pio

@asm_pio(in_shiftdir=PIO.SHIFT_LEFT)
def encoder():

    CLOCK_WISE = 1
    COUNTER_CLOCK_WISE = 2
 
    set(x, CLOCK_WISE)           # XɉE](CLOCK_SIZE)̒萔ݒ
    set(y, COUNTER_CLOCK_WISE)   # Yɍ](COUNTER_CLOCK_SIZE)̒萔ݒ
 
    label("start")
    wait(0, pin, 0)        # NbNLɂȂ܂ő҂
    jmp(pin, "on_cw")      # f[^MH̏ꍇAon_cw(E])ɕ
  
    # Counter CW           # łȂȂACCWi]j
    wait(1, pin, 0)        # NbNHɂȂ܂ő҂
    jmp(pin, "ccw_ok")     # f[^MH̏ꍇACCW OKi]OKjɕ
    jmp("start")           # łȂȂA]NGƔfĐ擪ɖ߂
    label("ccw_ok")        # --- ]OK̃t[  ----
    mov(isr, y)            # ISRY(COUNTER_CLOCK_WISE)ݒ
    push()                 # ISR̒lRX FIFO ɐݒ
    irq(0)                 # IRQtOFOIRQ𔭐AR[obN֐Ăяo
    jmp("start")         
 
    # CW                   # --- E]̃t[ ---
    label("on_cw")         #
    wait(1, pin, 0)        # NbNHɂȂ܂ő҂
    jmp(pin, "start")      # f[^MH̏ꍇAE]NGƔfĐ擪ɖ߂
                           # łȂȂE]OK
    mov(isr, x)            # ISR X(CLOCK_WISE)ݒ
    push()                 # ISR̒lRX FIFO ɐݒ
    irq(0)                 # IRQtOFOIRQ𔭐AR[obN֐Ăяo
    jmp("start")         
 
 
CLOCK_WISE = 1
COUNTER_CLOCK_WISE = 2

class RotaryEncoder:

    def __init__(self, clock, signal):
        self.counter = 0
        self.sm = StateMachine(0, encoder, freq = 2000, in_base = clock, jmp_pin = signal)
        self.sm.irq(self._handler)                  # R[obN֐̓o^
 
    def set_active(self):
        self.sm.active(1)
 
    def set_inactive(self):
        self.sm.active(0)
 
    def get_value(self):
        return self.counter

    # R[obN֐̒`(]IRQɂĂяo)
    def _handler(self, ev):
        val = self.sm.get()   
        if val == CLOCK_WISE:
            #print("->")
            self.counter += 1
        elif val == COUNTER_CLOCK_WISE:
            #print("<-")
            self.counter -= 1
#--------------------------------------------------------------



#--------------------------------------
# XgW  [^EGR[_phCopeXgEvO
#--------------------------------------
from machine import Pin
from machine import PWM
import utime
import encoder_pio                                 # PIOŃ[^GR[_hCo̓ǂݍ

ENC_CLK_PIN = 2
ENC_SIG_PIN = 3
LED_PIN = 25

enc_clk  = Pin(ENC_CLK_PIN, Pin.IN, Pin.PULL_UP)   # NbNMp͂̐ݒ (vAbvL)
enc_sig  = Pin(ENC_SIG_PIN, Pin.IN, Pin.PULL_UP)   #  f[^Mp͂̐ݒ (vAbvL)
led = Pin(LED_PIN, Pin.OUT)                        # LEDpo͂̐ݒ 
pwm = PWM(led)                                     # LED̖邳PWM𗘗p
duty = 0xff
pwm.duty_u16(duty)

enc = encoder_pio.RotaryEncoder(enc_clk, enc_sig)  # [^GR[_hCȍ
enc.set_active()                                   # [^GR[_hCőN

prev_val = 0
while True:
    utime.sleep(0.1)
    val = enc.get_value()                    # hCol擾 
    print("diff:{:d}({:d}->{:d})".format(val - prev_val, val,prev_val))
    if val == prev_val:
        continue
    elif val > prev_val:                     # GR[_̒lO傫ȂĂ
        if duty < 0x7fff:                    # dutyQ{ɂ
            duty <<=  1
            duty += 1
    elif val < prev_val:                     # GR[_̒lOȂĂ
        if duty > 0:                         # duty1/2ɂ
            duty >>=  1

    print("duty:{:04x}".format(duty))
    pwm.duty_u16(duty)                       # duty̒lݒ肵LED̖邳ς
    prev_val = val

enc.set_inactive()                           # [^GR[_hCo̒~
#--------------------------------------------------------------








