@@ -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 ) ]
3638const 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