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