2016-04-28 05:43:37 +00:00
|
|
|
import utime
|
|
|
|
|
2016-04-29 19:19:25 +00:00
|
|
|
from uheapq import heappop, heappush
|
2016-04-28 05:43:37 +00:00
|
|
|
from .utils import type_gen
|
2016-04-29 12:49:47 +00:00
|
|
|
from . import msg
|
2016-04-29 20:24:27 +00:00
|
|
|
from . import log
|
2016-04-28 05:43:37 +00:00
|
|
|
|
2016-05-05 12:28:10 +00:00
|
|
|
TOUCH_START = const(-1)
|
|
|
|
TOUCH_MOVE = const(-2)
|
|
|
|
TOUCH_END = const(-3)
|
|
|
|
MESSAGE = const(-4)
|
2016-04-29 19:19:25 +00:00
|
|
|
|
2016-05-03 16:35:11 +00:00
|
|
|
event_handlers = {
|
2016-05-05 12:28:10 +00:00
|
|
|
TOUCH_START: None,
|
|
|
|
TOUCH_MOVE: None,
|
|
|
|
TOUCH_END: None,
|
|
|
|
MESSAGE: None,
|
2016-04-30 13:57:08 +00:00
|
|
|
}
|
2016-04-29 19:19:25 +00:00
|
|
|
time_queue = []
|
2016-05-11 12:39:57 +00:00
|
|
|
schedule_ctr = 0
|
2016-04-29 19:19:25 +00:00
|
|
|
|
2016-04-29 19:48:59 +00:00
|
|
|
if __debug__:
|
|
|
|
# For performance stats
|
|
|
|
import array
|
|
|
|
log_delay_pos = 0
|
|
|
|
log_delay_rb_len = const(10)
|
|
|
|
log_delay_rb = array.array('i', [0] * log_delay_rb_len)
|
|
|
|
|
2016-05-02 14:22:22 +00:00
|
|
|
|
2016-05-05 12:22:40 +00:00
|
|
|
def __schedule(gen, args=(), time=None):
|
2016-05-11 12:39:57 +00:00
|
|
|
global schedule_ctr
|
2016-04-29 19:48:59 +00:00
|
|
|
if not time:
|
|
|
|
time = utime.ticks_us()
|
2016-05-11 12:39:57 +00:00
|
|
|
heappush(time_queue, (time, schedule_ctr, gen, args))
|
|
|
|
schedule_ctr += 1
|
2016-04-29 23:20:57 +00:00
|
|
|
|
2016-05-02 14:22:22 +00:00
|
|
|
|
2016-05-02 14:06:08 +00:00
|
|
|
class Wait():
|
2016-05-11 12:39:57 +00:00
|
|
|
|
2016-05-02 14:06:08 +00:00
|
|
|
def __init__(self, gens, wait_for=1, exit_others=True):
|
|
|
|
self.wait_for = wait_for
|
|
|
|
self.exit_others = exit_others
|
|
|
|
self.received = 0
|
|
|
|
self.callback = None
|
|
|
|
self.gens = gens
|
|
|
|
|
|
|
|
for g in gens:
|
2016-05-03 16:58:10 +00:00
|
|
|
__schedule(self._wait(g))
|
2016-05-02 14:06:08 +00:00
|
|
|
|
|
|
|
def _wait(self, gen):
|
|
|
|
if isinstance(gen, type_gen):
|
|
|
|
ret = yield from gen
|
|
|
|
else:
|
|
|
|
ret = yield gen
|
2016-04-29 23:20:57 +00:00
|
|
|
|
2016-05-02 14:06:08 +00:00
|
|
|
self.finish(gen, ret)
|
2016-04-29 23:20:57 +00:00
|
|
|
|
2016-05-02 14:06:08 +00:00
|
|
|
def finish(self, gen, result):
|
|
|
|
self.received += 1
|
2016-04-30 13:57:08 +00:00
|
|
|
|
2016-05-02 14:21:50 +00:00
|
|
|
if self.received == self.wait_for:
|
2016-05-05 12:22:40 +00:00
|
|
|
__schedule(self.callback, (gen, result))
|
2016-05-02 14:06:08 +00:00
|
|
|
self.callback = None
|
2016-04-29 19:48:59 +00:00
|
|
|
|
2016-05-02 14:06:08 +00:00
|
|
|
if self.exit_others:
|
|
|
|
for g in self.gens:
|
2016-05-11 12:39:57 +00:00
|
|
|
if isinstance(gen, type_gen):
|
|
|
|
g.close()
|
2016-04-29 19:48:59 +00:00
|
|
|
|
2016-05-02 14:22:22 +00:00
|
|
|
|
2016-04-29 19:48:59 +00:00
|
|
|
def sleep(us):
|
|
|
|
return utime.ticks_us() + us
|
|
|
|
|
2016-04-29 19:19:25 +00:00
|
|
|
|
2016-04-29 19:48:59 +00:00
|
|
|
def run_forever(start_gens):
|
2016-04-30 00:00:40 +00:00
|
|
|
if __debug__:
|
|
|
|
global log_delay_pos
|
|
|
|
global log_delay_rb
|
|
|
|
global log_delay_rb_len
|
|
|
|
|
2016-04-29 19:19:25 +00:00
|
|
|
delay_max = const(1000000)
|
|
|
|
|
2016-04-29 19:48:59 +00:00
|
|
|
for gen in start_gens:
|
2016-05-03 16:58:10 +00:00
|
|
|
__schedule(gen)
|
2016-04-29 19:48:59 +00:00
|
|
|
|
2016-04-29 19:19:25 +00:00
|
|
|
while True:
|
|
|
|
|
|
|
|
if time_queue:
|
2016-05-11 12:39:57 +00:00
|
|
|
t, _, _, _ = time_queue[0]
|
2016-04-29 19:19:25 +00:00
|
|
|
delay = t - utime.ticks_us()
|
|
|
|
else:
|
|
|
|
delay = delay_max
|
|
|
|
|
2016-04-30 00:00:40 +00:00
|
|
|
if __debug__:
|
|
|
|
# Adding current delay to ring buffer for performance stats
|
|
|
|
log_delay_rb[log_delay_pos] = delay
|
|
|
|
log_delay_pos = (log_delay_pos + 1) % log_delay_rb_len
|
|
|
|
|
|
|
|
event = msg.select(delay)
|
2016-04-29 19:19:25 +00:00
|
|
|
|
|
|
|
if event:
|
2016-05-02 14:22:22 +00:00
|
|
|
# Run interrupt handler
|
2016-05-03 16:35:11 +00:00
|
|
|
event_id, *args = event
|
|
|
|
event_id = -event_id
|
|
|
|
gen = event_handlers.get(event_id, None)
|
|
|
|
event_handlers[event_id] = None
|
|
|
|
if not gen:
|
|
|
|
log.info(__name__, 'No handler for event: %s', event)
|
|
|
|
continue
|
2016-04-29 19:19:25 +00:00
|
|
|
else:
|
2016-05-02 14:22:22 +00:00
|
|
|
if time_queue:
|
|
|
|
# Run something from the time queue
|
2016-05-11 12:39:57 +00:00
|
|
|
_, _, gen, args = heappop(time_queue)
|
2016-05-02 14:22:22 +00:00
|
|
|
else:
|
|
|
|
# Sleep again
|
|
|
|
delay = delay_max
|
|
|
|
continue
|
2016-04-29 19:19:25 +00:00
|
|
|
|
2016-05-05 12:22:40 +00:00
|
|
|
if not args:
|
|
|
|
args = None
|
2016-04-29 19:19:25 +00:00
|
|
|
try:
|
2016-05-03 16:35:11 +00:00
|
|
|
ret = gen.send(args)
|
2016-04-30 13:57:08 +00:00
|
|
|
|
2016-04-29 19:19:25 +00:00
|
|
|
except StopIteration as e:
|
2016-05-02 14:22:22 +00:00
|
|
|
log.debug(__name__, '%s finished', gen)
|
2016-04-29 19:19:25 +00:00
|
|
|
continue
|
2016-04-30 13:57:08 +00:00
|
|
|
|
2016-04-29 23:20:57 +00:00
|
|
|
except Exception as e:
|
2016-04-29 23:48:13 +00:00
|
|
|
log.exception(__name__, e)
|
2016-04-29 23:20:57 +00:00
|
|
|
continue
|
2016-04-29 19:19:25 +00:00
|
|
|
|
2016-05-03 16:35:11 +00:00
|
|
|
if isinstance(ret, int) and ret >= 0:
|
|
|
|
# Sleep until ret, call us later
|
2016-05-05 12:22:40 +00:00
|
|
|
__schedule(gen, (), ret)
|
2016-05-03 16:35:11 +00:00
|
|
|
|
|
|
|
elif isinstance(ret, int) and ret in event_handlers:
|
|
|
|
# Wait for event
|
|
|
|
if event_handlers[ret]:
|
2016-05-05 12:22:40 +00:00
|
|
|
event_handlers[ret].close()
|
2016-05-03 16:35:11 +00:00
|
|
|
event_handlers[ret] = gen
|
2016-04-29 19:19:25 +00:00
|
|
|
|
2016-05-02 14:06:08 +00:00
|
|
|
elif isinstance(ret, Wait):
|
2016-05-02 14:22:22 +00:00
|
|
|
# Register the origin generator as a waiting callback
|
2016-05-02 14:06:08 +00:00
|
|
|
ret.callback = gen
|
2016-04-30 13:57:08 +00:00
|
|
|
|
2016-04-29 19:19:25 +00:00
|
|
|
elif ret is None:
|
2016-05-02 14:22:22 +00:00
|
|
|
# Just call us asap
|
2016-05-03 16:58:10 +00:00
|
|
|
__schedule(gen)
|
2016-04-29 23:20:57 +00:00
|
|
|
|
2016-04-30 13:57:08 +00:00
|
|
|
else:
|
2016-05-03 16:35:11 +00:00
|
|
|
raise Exception('Unhandled result %s by %s' % (ret, gen))
|