-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Fix for Issue #4266 - second PWMAudioOut interferes with the first one #4809
Conversation
[I added "closes:" line to the initial comment, so that accepting this PR will automatically close the related issue] |
if (common_hal_audiopwmio_pwmaudioout_get_playing(self)) { | ||
common_hal_audiopwmio_pwmaudioout_stop(self); | ||
} |
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.
What I think I see is that by removing the "stop", dma_hw->timer[self->pacing_timer]
is no longer set to 0, causing each play-while-already-playing to allocate a new pacing timer.
If you revise your test program to repeatedly start a new looping sample without closing it first, does it soon fail due to "No DMA pacing timer found"?
I did not actually test anything, I just looked at the code.
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.
You are correct; we need to stop if the dma channel is currently playing. So, I've made modifications in common_hal_audiopwmio_pwmaudioout_play() to detect if that is the case and only do the 'stop' if the dma channel is already in use.
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.
there are also pre-commit changes that need attention. thanks for your continued work here!
if (self->dma.channel[0] < NUM_DMA_CHANNELS) { | ||
if (common_hal_audiopwmio_pwmaudioout_get_playing(self)) { |
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.
Note that ...get_playing checks for the dma channel number:
bool audio_dma_get_playing(audio_dma_t *dma) {
if (dma->channel[0] == NUM_DMA_CHANNELS) {
return false;
}
so this added check may be unnecessary. If it is necessary, please add a source comment why and check if PWMAudioOut needs the added check too.
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.
The issue is that in common_hal_audiopwmio_pwmaudioout_get_playing() we are accessing self->pacing_timer before it has been set. So, the second PWMAudioOut will reset the timer (and so stop the first one). I could either initialize self->pacing timer in audio_dma_init() or leave the current code as is. Which do you think would be cleaner?
Decided that initializing the pacing_timer was a better way to go, so made the appropriate changes. |
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.
I'm still fuzzy on how this works, but if it passes your testing and the testing I suggested, then let's give it a try. I didn't perform any testing myself.
For the RP2040 chips; in common_hal_audiopwmio_pwmaudioout_play() we were calling common_hal_audiopwmio_pwmaudioout_get_playing() and common_hal_audiopwmio_pwmaudioout_stop() early on; which means we were accessing the DMA channels before we had set them up by calling audio_dma_setup_playback(). The impact was to stop the DMA for the first PWMAudioOut when setting up the second. In addition, a break statement while checking for a pacing timer was outside the proper braces. Also (perhaps unrelated), a call to audio_dma_stop() in audio_dma_get_playing() was being made even when the channels were not busy.
Closes: #4266