cleanup
switch to an interrupt-driven implementation