Skip to content

Conversation

@KorribanMaster
Copy link

@KorribanMaster KorribanMaster commented Nov 19, 2025

This feature adds the generation of a continuous waveforms in the SimplePWM
In the future this may be expanded for waveform_up and ComplementaryPWM

The goal is to generate a continous PWM signal that will run continuosly without any gaps using a circular DMA stream. This will block forever when awaited

@KorribanMaster KorribanMaster marked this pull request as draft November 19, 2025 13:16
@xoviat
Copy link
Contributor

xoviat commented Nov 19, 2025

Can you make this into_ring_buffered and add a ring buffered file like in adc or usart?

@KorribanMaster
Copy link
Author

KorribanMaster commented Nov 19, 2025

Can you make this into_ring_buffered and add a ring buffered file like in adc or usart?

Yes i think that is doable although there is a little difference here as we are "sending" data to the peripheral here instead of receiving. I would suggest the name should then be along the waveform_ringbuffered ? Or are you thinking in the direction of RingBufferedPWM as a seperate struct alongside SimplePWM and ComplementaryPWM

Another option would be to solve it like the embassy-nrf crate, where this is called SequencePWM so it would be more idiomatic i think to call it SequencePWM. This would also align with my final goal to actually implement double buffering with the dma where possible similiar to the discussion in this stm32h7_hal leveraging the DMA double buffer support as detailed in Idea 1 in this issue but i wanted to deliver it in smaller steps

@xoviat
Copy link
Contributor

xoviat commented Nov 19, 2025

into_ring_buffered(self) -> RingBufferedWaveform<T: Instance> consumes the channel and returns PWMRingBuffer struct, which contains WritableDmaRingBuffer (already exists) and the channel number. Then you can either write continuously to the buffer to keep it fed, or do nothing and dma will keep going on its own. I think you can get the same struct from both the simple and complementary pwm.

Let me know if you have further questions on this.

@KorribanMaster
Copy link
Author

KorribanMaster commented Nov 20, 2025

Okay one more question to the function signature

//simple_pwm.rs
/// Simple PWM driver.
pub struct SimplePwm<'d, T: GeneralInstance4Channel> {
    inner: Timer<'d, T>,
}
....
impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
    /// Create a new simple PWM driver.
  pub fn into_ring_buffered<C: TimerChannel>(&mut self, dma: Peri<'_, impl super::Dma<T, C>>, duty: &[u16]) -> RingBufferedPWMChannel{
    }
    ...
}

// ringbuffered.rs

/// A single ring buffered channel of a pwm, obtained from [`SimplePwm::into_ring_buffered`],
/// It is not possible to change the pwm frequency because
/// the frequency configuration is shared with all four channels.
pub struct RingBufferedPwmChannel<'d, T: GeneralInstance4Channel> {
    timer: ManuallyDrop<Timer<'d, T>>,
    channel: Channel,
    duty_buffer: WritableDmaRingBuffer,
}

impl<'d, T: GeneralInstance4Channel> RingBufferedPwmChannel<'d, T> {
    /// Construct a ringbuffer filled with the given buffer data.
   
    pub fn reset(&mut self){ }

    /// Get the remaining writable dma samples.
    pub fn len(&mut self) -> Result<usize, Error> { }

    /// Get the full ringbuffer capacity.
    pub const fn cap(&self) -> usize { }

    pub fn write(&mut self, buf: &[W]) -> Result<(usize, usize), Error> {
        }

    pub fn write_immediate(&mut self, buf: &[W]) -> Result<(usize, usize), Error> {
    }

    /// Wait for any ring buffer write error.
    pub async fn wait_write_error(&mut self, dma: &mut impl DmaCtrl) -> Result<usize, Error> {
    }

    /// Write an exact number of elements to the ringbuffer.
    ///
    /// Returns the remaining write capacity in the buffer.
    #[allow(dead_code)]
    pub async fn write_exact(&mut self, buffer: &[W]) -> Result<usize, Error> {
        
    }

    fn write_raw(&mut self, dma: &mut impl DmaCtrl, buf: &[W]) -> Result<(usize, usize), Error> {
    }

    fn write_buf(&mut self, offset: usize, value: W) {
    }
}

Does this go into the right direction?

@xoviat
Copy link
Contributor

xoviat commented Nov 20, 2025

That's basically okay. There is a problem with the current static typing that prevents what I really want to do, but it requires some thought and I can play around with the typing after the feature is functional. Unless there is an objection, I will merge this and clean it up myself, if I think it needs some adjustment, if it is functional.

@KorribanMaster
Copy link
Author

Let me check whether this is fully functional when I will be back home on the Weekend

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants