1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
//! RingBuffered PWM driver.
use core::mem::ManuallyDrop;
use core::task::Waker;
use super::low_level::Timer;
use super::{Channel, GeneralInstance4Channel};
use crate::dma::WritableRingBuffer;
use crate::dma::ringbuffer::Error;
use crate::dma::word::Word;
/// A PWM channel that uses a DMA ring buffer for continuous waveform generation.
///
/// This allows you to continuously update PWM duty cycles via DMA without blocking the CPU.
/// The ring buffer enables smooth, uninterrupted waveform generation by automatically cycling
/// through duty cycle values stored in memory.
///
/// You can write new duty cycle values to the ring buffer while it's running, enabling
/// dynamic waveform generation for applications like motor control, LED dimming, or audio output.
///
/// # Example
/// ```ignore
/// let mut channel = pwm.ch1().into_ring_buffered_channel(dma_ch, &mut buffer);
/// channel.start(); // Start DMA transfer
/// channel.write(&[100, 200, 300]).ok(); // Update duty cycles
/// ```
pub struct RingBufferedPwmChannel<'d, T: GeneralInstance4Channel, W: Word + Into<T::Word>> {
timer: ManuallyDrop<Timer<'d, T>>,
ring_buf: WritableRingBuffer<'d, W>,
channel: Channel,
}
impl<'d, T: GeneralInstance4Channel, W: Word + Into<T::Word>> RingBufferedPwmChannel<'d, T, W> {
pub(crate) fn new(
timer: ManuallyDrop<Timer<'d, T>>,
channel: Channel,
ring_buf: WritableRingBuffer<'d, W>,
) -> Self {
Self {
timer,
ring_buf,
channel,
}
}
/// Start the ring buffer operation.
///
/// You must call this after creating it for it to work.
pub fn start(&mut self) {
self.ring_buf.start()
}
/// Clear all data in the ring buffer.
pub fn clear(&mut self) {
self.ring_buf.clear()
}
/// Write elements directly to the raw buffer. This can be used to fill the buffer before starting the DMA transfer.
pub fn write_immediate(&mut self, buf: &[W]) -> Result<(usize, usize), Error> {
self.ring_buf.write_immediate(buf)
}
/// Write elements from the ring buffer
/// Return a tuple of the length written and the length remaining in the buffer
pub fn write(&mut self, buf: &[W]) -> Result<(usize, usize), Error> {
self.ring_buf.write(buf)
}
/// Write an exact number of elements to the ringbuffer.
pub async fn write_exact(&mut self, buffer: &[W]) -> Result<usize, Error> {
self.ring_buf.write_exact(buffer).await
}
/// Wait for any ring buffer write error.
pub async fn wait_write_error(&mut self) -> Result<usize, Error> {
self.ring_buf.wait_write_error().await
}
/// The current length of the ringbuffer
pub fn len(&mut self) -> Result<usize, Error> {
self.ring_buf.len()
}
/// The capacity of the ringbuffer
pub const fn capacity(&self) -> usize {
self.ring_buf.capacity()
}
/// Set a waker to be woken when at least one byte is send.
pub fn set_waker(&mut self, waker: &Waker) {
self.ring_buf.set_waker(waker)
}
/// Request the DMA to reset. The configuration for this channel will not be preserved.
///
/// This doesn't immediately stop the transfer, you have to wait until is_running returns false.
pub fn request_reset(&mut self) {
self.ring_buf.request_reset()
}
/// Request the transfer to pause, keeping the existing configuration for this channel.
/// To restart the transfer, call [`start`](Self::start) again.
///
/// This doesn't immediately stop the transfer, you have to wait until is_running returns false.
pub fn request_pause(&mut self) {
self.ring_buf.request_pause()
}
/// Return whether DMA is still running.
///
/// If this returns false, it can be because either the transfer finished, or it was requested to stop early with request_stop.
pub fn is_running(&mut self) -> bool {
self.ring_buf.is_running()
}
/// Stop the DMA transfer and await until the buffer is empty.
///
/// This disables the DMA transfer's circular mode so that the transfer stops when all available data has been written.
///
/// This is designed to be used with streaming output data such as the I2S/SAI or DAC.
pub async fn stop(&mut self) {
self.ring_buf.stop().await
}
/// Enable the given channel.
pub fn enable(&mut self) {
self.timer.enable_channel(self.channel, true);
}
/// Disable the given channel.
pub fn disable(&mut self) {
self.timer.enable_channel(self.channel, false);
}
/// Check whether given channel is enabled
pub fn is_enabled(&self) -> bool {
self.timer.get_channel_enable_state(self.channel)
}
/// Get max duty value.
///
/// This value depends on the configured frequency and the timer's clock rate from RCC.
pub fn max_duty_cycle(&self) -> u16 {
let max: u32 = self.timer.get_max_compare_value().into();
assert!(max < u16::MAX as u32);
max as u16 + 1
}
/// Set the output polarity for a given channel.
pub fn set_polarity(&mut self, polarity: super::low_level::OutputPolarity) {
self.timer.set_output_polarity(self.channel, polarity);
}
/// Set the output compare mode for a given channel.
pub fn set_output_compare_mode(&mut self, mode: super::low_level::OutputCompareMode) {
self.timer.set_output_compare_mode(self.channel, mode);
}
}
|