adafruit / Adafruit_CircuitPython_HT16K33

Adafruit CircuitPython driver for the HT16K33, a LED matrix driver IC.
MIT License
41 stars 29 forks source link

implement non_blocking_marquee #114

Closed FoamyGuy closed 11 months ago

FoamyGuy commented 1 year ago

This adds a non_blocking_marquee() function that has basically the same API as the existing marquee() except that you need to call it repeatedly inside of your main loop, and it does not block. It returns instantly if it's not time to scroll yet, and process the scroll step if it is time.

This allows the main loop to be doing other things while the marquee is being scrolled. A basic demonstration is provided in the examples dir that blinks an on-board neopixel between two different colors at a rate different from the scrolling rate on the marquee.

It appears that black made some other formatting changes as well that weren't specifically related to the new non_blocking_marquee() functionality.

makermelissa commented 1 year ago

Make sure it works as expected with text like "Some long text ending with an ellipsis...". The dots can sometimes be tricky.

FoamyGuy commented 1 year ago

nonblocking_marquee.webm

Thank you for the pointer. The dots do work although they have slightly special behavior compared to the other characters since they are allowed to exist on the same segment as another different character. In practice that means if you have a string containing a chain of dot, then non-dot a few times over the marquee appears to pause for a bit of extra time because it doesn't have to scroll when it adds the dots.

I briefly toyed with logic to try to make it account for that and not pause that extra beat. But I abandonned it quickly as the logic gets rather complex since dots behave differently depending on whether the character to it's left is also a dot or not. Also if we did skip that pause it means that the viewer actually gets less time to "consume" the full string visually compared to strings that don't contain dots.

Tested with:

segment_display.non_blocking_marquee("CircuitPython <3 Long Message with dots .8.3.2.A....", delay=0.2)
makermelissa commented 1 year ago

I believe the blocking one handles the dots correctly. Maybe you can combine the two a bit to make the library a bit smaller.

FoamyGuy commented 1 year ago

Okay the latest commit has two main changes:

  1. the non-blocking marquee now matches the blocking marquee's behavior with regards to period characters. They both scroll the exact same way now
  2. The blocking marquee has been refactored to use the new non-blocking one which allows the removal of some duplicated code functionality.
  3. added an optional argument to both marquee's space_between which if True will add a space between the end of the string and beginning of the next one in the loop (if loop is True)

I carried out testing on a Feather S3 TFT. I think this is ready for review now.