Skip to content

Commit 56d155e

Browse files
committed
Add 'static bound to dma buffers, add PwmSeq wrapper, update demo with new api
1 parent 36e39e8 commit 56d155e

File tree

2 files changed

+196
-53
lines changed

2 files changed

+196
-53
lines changed

examples/pwm-demo/src/main.rs

Lines changed: 55 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ pub enum AppStatus {
3232
Demo4,
3333
}
3434

35+
type SeqBuffer = &'static mut [u16; 48];
36+
3537
#[rtic::app(device = crate::hal::pac, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)]
3638
const APP: () = {
3739
struct Resources {
@@ -40,13 +42,17 @@ const APP: () = {
4042
btn2: Pin<Input<PullUp>>,
4143
btn3: Pin<Input<PullUp>>,
4244
btn4: Pin<Input<PullUp>>,
43-
pwm: Pwm<PWM0>,
45+
// pwm: Pwm<PWM0>,
4446
#[init(AppStatus::Idle)]
4547
status: AppStatus,
48+
pwm: Option<PwmSeq<PWM0, SeqBuffer, SeqBuffer>>,
4649
}
4750

4851
#[init]
4952
fn init(mut ctx: init::Context) -> init::LateResources {
53+
static mut BUF0: [u16; 48] = [0u16; 48];
54+
static mut BUF1: [u16; 48] = [0u16; 48];
55+
5056
let _clocks = hal::clocks::Clocks::new(ctx.device.CLOCK).enable_ext_hfosc();
5157
ctx.core.DCB.enable_trace();
5258
ctx.core.DWT.enable_cycle_counter();
@@ -84,43 +90,45 @@ const APP: () = {
8490
btn2,
8591
btn3,
8692
btn4,
87-
pwm,
93+
pwm: pwm.load(Some(BUF0), Some(BUF1), false).ok(),
8894
}
8995
}
9096

9197
#[idle]
9298
fn idle(_: idle::Context) -> ! {
9399
rprintln!("Press a button to start a demo");
94100
loop {
95-
cortex_m::asm::wfi();
101+
cortex_m::asm::nop();
96102
}
97103
}
98104

99105
#[task(binds = PWM0, resources = [pwm])]
100106
fn on_pwm(ctx: on_pwm::Context) {
101-
let pwm = ctx.resources.pwm;
107+
let (buf0, buf1, pwm) = ctx.resources.pwm.take().unwrap().split();
102108
if pwm.is_event_triggered(PwmEvent::Stopped) {
103109
pwm.reset_event(PwmEvent::Stopped);
104110
rprintln!("PWM generation was stopped");
105111
}
112+
ctx.resources.pwm.replace(pwm.wrap(buf0, buf1));
106113
}
107114

108115
#[task(binds = GPIOTE, resources = [gpiote], schedule = [debounce])]
109116
fn on_gpiote(ctx: on_gpiote::Context) {
110117
ctx.resources.gpiote.reset_events();
111-
ctx.schedule.debounce(ctx.start + 3_000_000.cycles()).ok();
118+
ctx.schedule.debounce(ctx.start + 2_500_000.cycles()).ok();
112119
}
113120

114121
#[task(resources = [btn1, btn2, btn3, btn4, pwm, status])]
115122
fn debounce(ctx: debounce::Context) {
116-
static mut BUF: [u16; 48] = [0u16; 48];
117-
let status = ctx.resources.status;
123+
let (buf0, buf1, pwm) = ctx.resources.pwm.take().unwrap().split();
124+
let BUF0 = buf0.unwrap();
125+
let BUF1 = buf1.unwrap();
118126

119-
let pwm = ctx.resources.pwm;
120127
let max_duty = pwm.max_duty();
121128
let (ch0, ch1, ch2, ch3) = pwm.split_channels();
122129
let (grp0, grp1) = pwm.split_groups();
123130

131+
let status = ctx.resources.status;
124132
if ctx.resources.btn1.is_low().unwrap() {
125133
match status {
126134
AppStatus::Demo1B => {
@@ -143,68 +151,65 @@ const APP: () = {
143151
pwm.set_duty_on_common(max_duty / 10);
144152
}
145153
}
146-
}
147-
if ctx.resources.btn2.is_low().unwrap() {
154+
*ctx.resources.pwm = pwm.load(Some(BUF0), Some(BUF1), false).ok();
155+
} else if ctx.resources.btn2.is_low().unwrap() {
148156
match status {
149157
AppStatus::Demo2B => {
150158
rprintln!("DEMO 2C: Play grouped sequence 4 times");
151159
*status = AppStatus::Demo2C;
152160
let ampl = max_duty as i32 / 20;
153-
let len: usize = 12;
161+
let len: usize = BUF0.len() / 2;
154162
// In `Grouped` mode, each step consists of two values [G0, G1]
155163
for x in 0..len {
156-
BUF[x * 2] = triangle_wave(x, len, ampl, 6, 0) as u16;
157-
BUF[x * 2 + 1] = triangle_wave(x, len, ampl, 0, 0) as u16;
164+
BUF0[x * 2] = triangle_wave(x, len, ampl, 6, 0) as u16;
165+
BUF0[x * 2 + 1] = triangle_wave(x, len, ampl, 0, 0) as u16;
158166
}
167+
BUF1.copy_from_slice(&BUF0[..]);
159168
pwm.set_load_mode(LoadMode::Grouped)
160169
.set_step_mode(StepMode::Auto)
161-
.set_seq_refresh(Seq::Seq0, 70) // Playback rate (periods per step)
162-
.set_seq_refresh(Seq::Seq1, 30)
170+
.set_seq_refresh(Seq::Seq0, 30) // Playback rate (periods per step)
171+
.set_seq_refresh(Seq::Seq1, 10)
163172
.repeat(4);
164-
pwm.load_seq(Seq::Seq0, &BUF[..len]).ok();
165-
pwm.load_seq(Seq::Seq1, &BUF[len..(2 * len)]).ok();
166-
pwm.start_seq(Seq::Seq0);
173+
*ctx.resources.pwm = pwm.load(Some(BUF0), Some(BUF1), true).ok();
167174
}
168175
AppStatus::Demo2A => {
169176
rprintln!("DEMO 2B: Loop individual sequences");
170177
*status = AppStatus::Demo2B;
171178
let ampl = max_duty as i32 / 5;
172179
let offset = max_duty as i32 / 300;
173-
let len = 12;
180+
let len = BUF0.len() / 4;
174181
// In `Individual` mode, each step consists of four values [C0, C1, C2, C3]
175182
for x in 0..len {
176-
BUF[4 * x] = triangle_wave(x, len, ampl, 0, offset) as u16;
177-
BUF[4 * x + 1] = triangle_wave(x, len, ampl, 3, offset) as u16;
178-
BUF[4 * x + 2] = triangle_wave(x, len, ampl, 6, offset) as u16;
179-
BUF[4 * x + 3] = triangle_wave(x, len, ampl, 9, offset) as u16;
183+
BUF0[4 * x] = triangle_wave(x, len, ampl, 0, offset) as u16;
184+
BUF0[4 * x + 1] = triangle_wave(x, len, ampl, 3, offset) as u16;
185+
BUF0[4 * x + 2] = triangle_wave(x, len, ampl, 6, offset) as u16;
186+
BUF0[4 * x + 3] = triangle_wave(x, len, ampl, 9, offset) as u16;
180187
}
188+
BUF1.copy_from_slice(&BUF0[..]);
181189
pwm.set_load_mode(LoadMode::Individual)
182190
.set_seq_refresh(Seq::Seq0, 30)
183191
.set_seq_refresh(Seq::Seq1, 30)
184192
.loop_inf();
185-
pwm.load_seq(Seq::Seq0, &BUF[..(4 * len)]).ok();
186-
pwm.load_seq(Seq::Seq1, &BUF[..(4 * len)]).ok();
187-
pwm.start_seq(Seq::Seq0);
193+
*ctx.resources.pwm = pwm.load(Some(BUF0), Some(BUF1), true).ok();
188194
}
189195
_ => {
190196
rprintln!("DEMO 2A: Play common sequence once");
191197
*status = AppStatus::Demo2A;
192-
let len = 10;
198+
let len = BUF0.len();
193199
// In `Common` mode, each step consists of one value for all channels.
194200
for x in 0..len {
195-
BUF[x] = triangle_wave(x, len, 2000, 0, 100) as u16;
201+
BUF0[x] = triangle_wave(x, len, 2000, 0, 100) as u16;
196202
}
203+
BUF1.copy_from_slice(&BUF0[..]);
197204
pwm.set_load_mode(LoadMode::Common)
198205
.set_step_mode(StepMode::Auto)
199-
.set_seq_refresh(Seq::Seq0, 50)
200-
.one_shot()
201-
.load_seq(Seq::Seq0, &BUF[..len])
202-
.ok();
203-
pwm.start_seq(Seq::Seq0);
206+
.set_seq_refresh(Seq::Seq0, 20)
207+
.set_seq_refresh(Seq::Seq1, 20)
208+
.one_shot();
209+
*ctx.resources.pwm = pwm.load(Some(BUF0), Some(BUF1), true).ok();
204210
}
205211
}
206-
}
207-
if ctx.resources.btn3.is_low().unwrap() {
212+
} else if ctx.resources.btn3.is_low().unwrap() {
208213
match status {
209214
AppStatus::Demo3 => {
210215
rprintln!("DEMO 3: Next step");
@@ -215,46 +220,46 @@ const APP: () = {
215220
pwm.stop();
216221
*status = AppStatus::Idle;
217222
}
223+
ctx.resources.pwm.replace(pwm.wrap(Some(BUF0), Some(BUF1)));
218224
}
219225
_ => {
220226
rprintln!("DEMO 3: Manually step through sequence");
221227
*status = AppStatus::Demo3;
222228
let amplitude = max_duty as i32 / 20;
223229
let offset = max_duty as i32 / 300;
224-
let len = 6;
230+
let len = BUF0.len();
225231
for x in 0..len {
226-
BUF[x] = triangle_wave(x, len, amplitude, 0, offset) as u16;
232+
BUF0[x] = triangle_wave(x * 8, len, amplitude, 0, offset) as u16;
227233
}
234+
BUF1.copy_from_slice(&BUF0[..]);
228235
pwm.set_load_mode(LoadMode::Common)
229236
.set_step_mode(StepMode::NextStep)
230237
.loop_inf();
231-
pwm.load_seq(Seq::Seq0, &BUF[..(len / 2)]).ok();
232-
pwm.load_seq(Seq::Seq1, &BUF[(len / 2)..len]).ok();
233-
pwm.start_seq(Seq::Seq0);
238+
*ctx.resources.pwm = pwm.load(Some(BUF0), Some(BUF1), true).ok();
234239
}
235240
}
236-
}
237-
if ctx.resources.btn4.is_low().unwrap() {
241+
} else if ctx.resources.btn4.is_low().unwrap() {
238242
rprintln!("DEMO 4: Waveform mode");
239243
*status = AppStatus::Demo4;
240-
let len = 12;
244+
let len = BUF0.len() / 4;
241245
// In `Waveform` mode, each step consists of four values [C0, C1, C2, MAX_DUTY]
242246
// So the maximum duty cycle can be set on a per step basis, affecting the PWM frequency
243247
for x in 0..len {
244248
let current_max = x * 2_200 + 5_000;
245-
BUF[4 * x] = ((x % 3) * current_max / (5 * (x + 1))) as u16;
246-
BUF[4 * x + 1] = (((x + 1) % 3) * current_max / (5 * (x + 1))) as u16;
247-
BUF[4 * x + 2] = (((x + 2) % 3) * current_max / (5 * (x + 1))) as u16;
248-
BUF[4 * x + 3] = current_max as u16;
249+
BUF0[4 * x] = ((x % 3) * current_max / (5 * (x + 1))) as u16;
250+
BUF0[4 * x + 1] = (((x + 1) % 3) * current_max / (5 * (x + 1))) as u16;
251+
BUF0[4 * x + 2] = (((x + 2) % 3) * current_max / (5 * (x + 1))) as u16;
252+
BUF0[4 * x + 3] = current_max as u16;
249253
}
254+
BUF1.copy_from_slice(&BUF0[..]);
250255
pwm.set_load_mode(LoadMode::Waveform)
251256
.set_step_mode(StepMode::Auto)
252257
.set_seq_refresh(Seq::Seq0, 150)
253258
.set_seq_refresh(Seq::Seq1, 150)
254259
.loop_inf();
255-
pwm.load_seq(Seq::Seq0, &BUF[..(4 * len)]).ok();
256-
pwm.load_seq(Seq::Seq1, &BUF[..(4 * len)]).ok();
257-
pwm.start_seq(Seq::Seq0);
260+
*ctx.resources.pwm = pwm.load(Some(BUF0), Some(BUF1), true).ok();
261+
} else {
262+
*ctx.resources.pwm = pwm.load(Some(BUF0), Some(BUF1), false).ok();
258263
}
259264
}
260265

0 commit comments

Comments
 (0)