-
Notifications
You must be signed in to change notification settings - Fork 1.3k
rp2040: add a background write with looping to StateMachines #6300
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
the sequence has to be a minimum length, 8 entries, but this problem is not detected. I don't THINK this is an insurmountable problem.
@ZodiusInfuser one use case for this is better support for the Pimoroni servo board! can you check it out and give some feedback? My implementation of 'pulsle group' based on your code is at https://gist.github.com/jepler/5043843c9c196ad9d513e9f89e48ba79 including a little servo-style demo. Once this is added to CircuitPython, we hope you'd be able to adapt your lib to have full functionality with CircuitPython. |
@jepler Thanks for tagging me! This looks pretty cool, and would be great to have such functionality within CircuitPython! My time is pretty limited for the next few weeks, so not sure if I will get chance to look at it in detail before next month. From a cursory glance though it seems your
Great to see that staggered start!
^ These took me so long to get rid of 😅, and is where much of the complexity in my |
Thanks @ZodiusInfuser ! If there's nothing that stands out as "obviously too broken to build on" we'll keep moving forward on this PR. |
Is it possible for it to auto switch to a new sequence after it has finished the first? To overcome some of the glitches I experienced, I ended up having There was also the triple buffering thing I did, where the new sequence buffer would only be provided to the DMA when it is fully generated. Sounds like that could already be handled by what you have written? Also, a "nice to have" feature that's on my own to-do list is some kind of interrupt callback when a sequence is loaded or looped. My intention being that on my walking robots I want to know when new data has been loaded, so I know I have 20ms to calculate the IK for the next sequence if I want the absolute lowest latency. For my C++ implementation I was considering having the DMA interrupt trigger a timer interrupt for a few microseconds later, so as to not stall the PIO. |
Oh, another thing. I don't know if CircuitPython already handles PIO cleanup nicely already, but I had many headaches getting it working for the |
as is, there's no way to guarantee a sequence plays at most once, but if you call the start_continuous_write signal again before the sequence is done that's what will happen. Of course, a GC pause or something else could leap out at just the wrong moment and gnaw your face off.. |
I'm wondering if a different API is better. `def background_write(*buffers: ReadableBuffer, loop=Optional[ReadableBuffer]): ... This would 'play' each positional argument buffer exactly once, and then play the This change would be to enable the use case where a special 'transitional' output needs to be played just once, to do with a change in PWM duty cycle that crosses the buffer wrap point. It also enables the use case where you want to write something just once, but in the background. This would complicate the implementation a bit, but if it's useful then so be it. |
Now a 'once' and a 'loop' buffer can be specified. 'once' is useful for things like writing a neopixel strip in the background, if you can guarantee the buffer contents are stable until the write is complete. 'loop' is useful for periodic things, like pwm & servos. both together are useful for some special cases of pwm/servo, where a transitional waveform needs to be played for one repetition and then a new waveform needs to be played after that. The API is renamed to reflect that it's a more generic 'background' operation.
I ended up adding support for one 'once' buffer and one 'loop' buffer. this covers the glitch-free pwm case, and also the simplest case of non-looping background writing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A great addition! I tested this with the gist example, and I get random movement of servos, as expected. The examples use start_continuous_write()
instead of the newer name background_write()
.
whoops, I thought I'd updated the PR in adafruit_pioasm. I'll double check. Thanks for the merge! |
This adds the ability to background-write to a StateMachine, either once or in a loop (or both). It can be seen in action driving servos in the parallel pull request adafruit/Adafruit_CircuitPython_PIOASM#41
The examples below worked with an older version of the PR:
"Servo Cluster" / "PWM Cluster" works: https://gist.github.com/jepler/5043843c9c196ad9d513e9f89e48ba79 as does this simpler test program:
Closes: #6295