nrf-rs / microbit

A Rust crate for BBC micro:bit development
BSD Zero Clause License
276 stars 61 forks source link

Non-blocking display: change the order of GPIO writes #129

Closed mattheww closed 9 months ago

mattheww commented 9 months ago

Closes #108

On the micro:bit v2 the GPIO pins are on two ports, and it takes four IO writes to update all the pins: one "clear multiple pins" and one "set multiple pins" per port.

(It's possible to set pins to both low and high using OUT, but we can't use that as we don't own all the pins on the port.)

So there is a brief period where the pins are in a mix of the old and new states, and evidently in debug builds this can persist for long enough to be visible.

We can fix this by changing the order of writes: make the first write be the one that makes the old row dark, and the last one be the one that makes the new row light.

We might as well also arrange the code so that it doesn't perform any calculations between the GPIO writes (on the theory that in debug mode the compiler probably won't be reordering things).

With those changes I no longer see spurious lighting in the example image from #108.

mattheww commented 9 months ago

I believe this sort of "tearing" isn't possible on the micro:bit v1, whichever order we use for writes, because the write that turns on a row turns off all the columns we don't want to be lit, and the write that can turn on columns turns off the rows that we don't want to be lit (to light an LED, we have to set the row bit and clear the col bit).

But I've left the order of writes for micro:bit v1 as it was before, out of prudence.

(Animations on the micro:bit v1 display look poor in debug builds, but they always did.)