Open peterhinch opened 1 year ago
Hi Peter, Thanks for these options to improve this implementation! Sorry for the long delay in responding. It's been a busy summer and MicroPython fun has taken a back seat. I'll try to carve out some time to dig into your encoder implementation.
The first question I have is about reentrancy. On the ESP32 and ESP8266 ports the pin interrupt code queues the callbacks into the scheduler. This should protect the rotary callback code from reentrancy issues as this code will run to completion before it is called again by the scheduler. I assumed that the other ports (stm32, mimxrt, rp2, ...) would be consistent in how the pin callbacks are handled (even though they don't appear to use the scheduler). But, maybe that is a wrong assumption?
IRQ's may be hard or soft. Soft IRQ's are run by the scheduler and are protected, however they suffer latency measured in ms. Hard IRQ's are only supported on some platforms (e.g. STM). They run with latency on the order of 15μs. Coding them requires care - see para on reentrancy.
There is the option always to use soft IRQ's.
One potential issue with latency/slow ISR's is that pulses might be missed. In many cases with a rotary control the user would never notice. The case where the encoder driver tracks mechanical detents is where missing pulses could matter, with alignment gradually drifting.
As a bit of background nearly 50 years ago (!) I designed a hardware interface for an optical encoder. It was on a machine tool and had to be pulse-perfect. That was a baptism of fire. For a digital circuit involving a handful of simple chips it was remarkably hard to get right and was my first encounter with metastability - something little-known in 1974.
I know we discussed encoders in the past and I'm not sure at what point we left the discussion - I have talked with a number of people and thought it worth sharing the outcome with you. It was only when I was planning adding encoder support to micro-gui that I realised that there was a risk of great swathes of GUI code running in an ISR context.
For context please see this doc on the design of encoder drivers and this driver.
The following specifics are potential issues:
The driver cited above has the following characteristics. ISR's run in 36μs on a Pyboard 1.1 and 50μs on ESP32 (soft ISR's run fast, but are subject to latency of multiple ms). The ISR design aims to allow for potential latency, detecting missed bounce transitions. Hard ISR's are used if available because latency limits allowable rotational speed.