rework main wait loop

- accumulate rapid successive changes into one block
- but process changes as soon as there's at least 'latency' after last change
- sleep until changes are queued but wakeup as soon as something happens
- quickly and gracefully stop the loop
- use FSM for state machine