@@ -32,6 +32,8 @@ pub enum AppStatus {
32
32
Demo4 ,
33
33
}
34
34
35
+ type SeqBuffer = & ' static mut [ u16 ; 48 ] ;
36
+
35
37
#[ rtic:: app( device = crate :: hal:: pac, peripherals = true , monotonic = rtic:: cyccnt:: CYCCNT ) ]
36
38
const APP : ( ) = {
37
39
struct Resources {
@@ -40,13 +42,17 @@ const APP: () = {
40
42
btn2 : Pin < Input < PullUp > > ,
41
43
btn3 : Pin < Input < PullUp > > ,
42
44
btn4 : Pin < Input < PullUp > > ,
43
- pwm : Pwm < PWM0 > ,
45
+ // pwm: Pwm<PWM0>,
44
46
#[ init( AppStatus :: Idle ) ]
45
47
status : AppStatus ,
48
+ pwm : Option < PwmSeq < PWM0 , SeqBuffer , SeqBuffer > > ,
46
49
}
47
50
48
51
#[ init]
49
52
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
+
50
56
let _clocks = hal:: clocks:: Clocks :: new ( ctx. device . CLOCK ) . enable_ext_hfosc ( ) ;
51
57
ctx. core . DCB . enable_trace ( ) ;
52
58
ctx. core . DWT . enable_cycle_counter ( ) ;
@@ -84,43 +90,45 @@ const APP: () = {
84
90
btn2,
85
91
btn3,
86
92
btn4,
87
- pwm,
93
+ pwm : pwm . load ( Some ( BUF0 ) , Some ( BUF1 ) , false ) . ok ( ) ,
88
94
}
89
95
}
90
96
91
97
#[ idle]
92
98
fn idle ( _: idle:: Context ) -> ! {
93
99
rprintln ! ( "Press a button to start a demo" ) ;
94
100
loop {
95
- cortex_m:: asm:: wfi ( ) ;
101
+ cortex_m:: asm:: nop ( ) ;
96
102
}
97
103
}
98
104
99
105
#[ task( binds = PWM0 , resources = [ pwm] ) ]
100
106
fn on_pwm ( ctx : on_pwm:: Context ) {
101
- let pwm = ctx. resources . pwm ;
107
+ let ( buf0 , buf1 , pwm) = ctx. resources . pwm . take ( ) . unwrap ( ) . split ( ) ;
102
108
if pwm. is_event_triggered ( PwmEvent :: Stopped ) {
103
109
pwm. reset_event ( PwmEvent :: Stopped ) ;
104
110
rprintln ! ( "PWM generation was stopped" ) ;
105
111
}
112
+ ctx. resources . pwm . replace ( pwm. wrap ( buf0, buf1) ) ;
106
113
}
107
114
108
115
#[ task( binds = GPIOTE , resources = [ gpiote] , schedule = [ debounce] ) ]
109
116
fn on_gpiote ( ctx : on_gpiote:: Context ) {
110
117
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 ( ) ;
112
119
}
113
120
114
121
#[ task( resources = [ btn1, btn2, btn3, btn4, pwm, status] ) ]
115
122
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 ( ) ;
118
126
119
- let pwm = ctx. resources . pwm ;
120
127
let max_duty = pwm. max_duty ( ) ;
121
128
let ( ch0, ch1, ch2, ch3) = pwm. split_channels ( ) ;
122
129
let ( grp0, grp1) = pwm. split_groups ( ) ;
123
130
131
+ let status = ctx. resources . status ;
124
132
if ctx. resources . btn1 . is_low ( ) . unwrap ( ) {
125
133
match status {
126
134
AppStatus :: Demo1B => {
@@ -143,68 +151,65 @@ const APP: () = {
143
151
pwm. set_duty_on_common ( max_duty / 10 ) ;
144
152
}
145
153
}
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 ( ) {
148
156
match status {
149
157
AppStatus :: Demo2B => {
150
158
rprintln ! ( "DEMO 2C: Play grouped sequence 4 times" ) ;
151
159
* status = AppStatus :: Demo2C ;
152
160
let ampl = max_duty as i32 / 20 ;
153
- let len: usize = 12 ;
161
+ let len: usize = BUF0 . len ( ) / 2 ;
154
162
// In `Grouped` mode, each step consists of two values [G0, G1]
155
163
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 ;
158
166
}
167
+ BUF1 . copy_from_slice ( & BUF0 [ ..] ) ;
159
168
pwm. set_load_mode ( LoadMode :: Grouped )
160
169
. 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 )
163
172
. 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 ( ) ;
167
174
}
168
175
AppStatus :: Demo2A => {
169
176
rprintln ! ( "DEMO 2B: Loop individual sequences" ) ;
170
177
* status = AppStatus :: Demo2B ;
171
178
let ampl = max_duty as i32 / 5 ;
172
179
let offset = max_duty as i32 / 300 ;
173
- let len = 12 ;
180
+ let len = BUF0 . len ( ) / 4 ;
174
181
// In `Individual` mode, each step consists of four values [C0, C1, C2, C3]
175
182
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 ;
180
187
}
188
+ BUF1 . copy_from_slice ( & BUF0 [ ..] ) ;
181
189
pwm. set_load_mode ( LoadMode :: Individual )
182
190
. set_seq_refresh ( Seq :: Seq0 , 30 )
183
191
. set_seq_refresh ( Seq :: Seq1 , 30 )
184
192
. 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 ( ) ;
188
194
}
189
195
_ => {
190
196
rprintln ! ( "DEMO 2A: Play common sequence once" ) ;
191
197
* status = AppStatus :: Demo2A ;
192
- let len = 10 ;
198
+ let len = BUF0 . len ( ) ;
193
199
// In `Common` mode, each step consists of one value for all channels.
194
200
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 ;
196
202
}
203
+ BUF1 . copy_from_slice ( & BUF0 [ ..] ) ;
197
204
pwm. set_load_mode ( LoadMode :: Common )
198
205
. 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 ( ) ;
204
210
}
205
211
}
206
- }
207
- if ctx. resources . btn3 . is_low ( ) . unwrap ( ) {
212
+ } else if ctx. resources . btn3 . is_low ( ) . unwrap ( ) {
208
213
match status {
209
214
AppStatus :: Demo3 => {
210
215
rprintln ! ( "DEMO 3: Next step" ) ;
@@ -215,46 +220,46 @@ const APP: () = {
215
220
pwm. stop ( ) ;
216
221
* status = AppStatus :: Idle ;
217
222
}
223
+ ctx. resources . pwm . replace ( pwm. wrap ( Some ( BUF0 ) , Some ( BUF1 ) ) ) ;
218
224
}
219
225
_ => {
220
226
rprintln ! ( "DEMO 3: Manually step through sequence" ) ;
221
227
* status = AppStatus :: Demo3 ;
222
228
let amplitude = max_duty as i32 / 20 ;
223
229
let offset = max_duty as i32 / 300 ;
224
- let len = 6 ;
230
+ let len = BUF0 . len ( ) ;
225
231
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 ;
227
233
}
234
+ BUF1 . copy_from_slice ( & BUF0 [ ..] ) ;
228
235
pwm. set_load_mode ( LoadMode :: Common )
229
236
. set_step_mode ( StepMode :: NextStep )
230
237
. 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 ( ) ;
234
239
}
235
240
}
236
- }
237
- if ctx. resources . btn4 . is_low ( ) . unwrap ( ) {
241
+ } else if ctx. resources . btn4 . is_low ( ) . unwrap ( ) {
238
242
rprintln ! ( "DEMO 4: Waveform mode" ) ;
239
243
* status = AppStatus :: Demo4 ;
240
- let len = 12 ;
244
+ let len = BUF0 . len ( ) / 4 ;
241
245
// In `Waveform` mode, each step consists of four values [C0, C1, C2, MAX_DUTY]
242
246
// So the maximum duty cycle can be set on a per step basis, affecting the PWM frequency
243
247
for x in 0 ..len {
244
248
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 ;
249
253
}
254
+ BUF1 . copy_from_slice ( & BUF0 [ ..] ) ;
250
255
pwm. set_load_mode ( LoadMode :: Waveform )
251
256
. set_step_mode ( StepMode :: Auto )
252
257
. set_seq_refresh ( Seq :: Seq0 , 150 )
253
258
. set_seq_refresh ( Seq :: Seq1 , 150 )
254
259
. 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 ( ) ;
258
263
}
259
264
}
260
265
0 commit comments