# mPy - function implementing non blocking keyboard
# Copyright by Anthony Vogelaar, Perth Scotland
# rev 0.10  2025-10-07  initial release

import	sys, select

# implemented:
# nbInput(statics=dict(buff=bytearray(0), poll=None))  -->  str | None

# ============================ nbKeyb ===========================

# As Thonny is line based it works on this platform (a line after b'\r\n') 
# Working on character base when connected to a terminal
#    $ picocom -b 115200 --imap lfcrlf /dev/ttyACM0 [/dev/ttyUSB0]
def nbInput(statics=dict(buff=bytearray(0), poll=None)):
    if not statics['poll']:
        statics['poll'] = select.poll() 		            	# Set up serial input polling object
        statics['poll'].register(sys.stdin, select.POLLIN)		# Register polling object
    while statics['poll'].poll(0) and (ch := sys.stdin.buffer.read(1)):
        if ch in b'\r\n':
            res = statics['buff']
            statics['buff'] = bytearray(0)
            if res: return res.decode()
        else:
            statics['buff'] += ch

# ============================ tests ==============================

if __name__ == '__main__':
    
    import	time

    # observe blocking input
    def test1():
        while True:
            if s := input(): print('input:', s)
            print('*', end='')
            time.sleep_ms(100)


    # observe non blocking nbInput
    def test2():
        while True:
            if s := nbInput(): print('keyb:', s)
            print('*', end='')
            time.sleep_ms(100)


    # measuring non active nbInput fall through time, dt = 100 uSec (asyncio approx 1 mSec)
    def test3():
        while True:
            t1 = time.ticks_us()
            s  = nbInput()
            t2 = time.ticks_us()
            print(time.ticks_diff(t2, t1))
            time.sleep(1)


    # cooperative multi-tasking example in a class
    class Test4:

        def __init__(self):
            self.t_last = time.ticks_ms()
            try:
                while True:
                    self.task1()
                    self.task2()
            except:
                print('\ntest4 terminated')


        # print '*' @ 1 Sec
        def task1(self):
            now = time.ticks_ms()
            if time.ticks_diff(now, self.t_last) >= 1000:
                print('*', end='')
                self.t_last = now


        def task2(self):
            if s := nbInput():
                print('from keyboard:', s)
            
            
    #test3()
    Test4()

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