# Demonstrating multi-tasking using IRQ's
# Copyright by Anthony Vogelaar, Perth Scotland
# rev 0.10  2025-07-31  initial release

from	machine	import	Pin, Timer
import	time

# ========================== timer IRQ =================================

# https://docs.micropython.org/en/latest/esp32/quickref.html#timers

# function runs for 10 seconds then returns to REPL
def test1():
    print('start of test1')
    for i in range(10):
        print(i,  end=' ')
        time.sleep(1)
    print('\nend of test1')


# for 10 seconds test2 and timer IRQ then REPL and timer IRQ
def test2():
    
    # handling timer IRQ
    def onTimer(sender):
        print('!', end=' ')
        
        
    print('Terminate this application with Ctrl-d')
    print('start of test2')
    timer = Timer(3, mode=Timer.PERIODIC, freq=2, callback=onTimer)
    for i in range(10):
        print(i,  end=' ')
        time.sleep(1)
    print('\nend of test2')
    

n = 0

# n is incremented at 10Hz by timer IRQ
def test3():
    
    # handling timer IRQ
    def onTimer(sender):
        global n
        n += 1
            
    print('Terminate this application with Ctrl-d')
    print('start of test3')
    timer = Timer(3, mode=Timer.PERIODIC, freq=10, callback=onTimer)
    print('end of test3')

# ========================= button irq ============================

# https://docs.micropython.org/en/latest/library/machine.Pin.html#machine-pin

msg = 'Btn pressed'

# print msg when button SW1 pressed
def test4():
    
    # handling button IRQ
    def onBtn(sender):
        print(msg)
        
    print('test4 running')
    btn = Pin(14, Pin.IN, Pin.PULL_UP)
    btn.irq(onBtn, Pin.IRQ_FALLING)
#    while True:
#        print('*', end='')
#        time.sleep(1)


msg_down = 'down'
msg_up   = 'up'

# print 'down' on button SW1 pressed, 'up' when released
def test5():
    
    # handling button IRQ
    def onBtn(sender):
        print(msg_up) if btn() else print(msg_down)        
        
    print('test5 running')
    btn = Pin(14, Pin.IN, Pin.PULL_UP)
    btn.irq(onBtn, Pin.IRQ_FALLING | Pin.IRQ_RISING)


# measuring GPIO-14 pulse width
class Test6:
    
    def __init__(self):
        print('terminate with Ctrl-c ...')
        self.t1  = None
        self.t2  = None
        self.btn = Pin(14, Pin.IN, Pin.PULL_UP)
        self.btn.irq(self.onBtn, Pin.IRQ_FALLING | Pin.IRQ_RISING)
        while True:
            if self.t2 != None:
                print(f'duration is {time.ticks_diff(self.t2, self.t1)/1000:.3f} Sec')
                self.t1 = None; self.t2 = None
            
    
    # handling button IRQ
    def onBtn(self, sender):
        if   self.t1 == None and not self.btn(): self.t1 = time.ticks_ms()		# if down
        elif self.t2 == None and     self.btn(): self.t2 = time.ticks_ms()		# if up
            
        
# ================================= main ====================================

#test5()
Test6()

# ================================= end =====================================
