aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2023-05-02 18:03:00 +0000
committerGitHub <[email protected]>2023-05-02 18:03:00 +0000
commit2afa08c9236d386cae7920d9e7f20803a2c6b433 (patch)
tree9b744a8435eabd338109f44fd2c69ec6b06eb5c3
parentb2047c435133c6bd11918e89af81cab75c3354f1 (diff)
parent7a36072a15b2164a903ae3f36ee251eaf311216d (diff)
Merge #1425
1425: rp pio, round 2 r=Dirbaio a=pennae another round of bugfixes for pio, and some refactoring. in the end we'd like to make pio look like all the other modules and not expose traits that provide all the methods of a type, but put them onto the type itself. traits only make much sense, even if we added an AnyPio and merged the types for the member state machines (at the cost of at least a u8 per member of Pio). Co-authored-by: pennae <[email protected]>
-rw-r--r--embassy-rp/src/pio.rs482
-rw-r--r--examples/rp/src/bin/pio_async.rs34
-rw-r--r--examples/rp/src/bin/pio_dma.rs10
-rw-r--r--examples/rp/src/bin/pio_hd44780.rs243
-rw-r--r--examples/rp/src/bin/ws2812-pio.rs15
5 files changed, 444 insertions, 340 deletions
diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs
index 7faec10b5..5433d3f21 100644
--- a/embassy-rp/src/pio.rs
+++ b/embassy-rp/src/pio.rs
@@ -5,14 +5,14 @@ use core::sync::atomic::{compiler_fence, Ordering};
5use core::task::{Context, Poll}; 5use core::task::{Context, Poll};
6 6
7use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; 7use embassy_cortex_m::interrupt::{Interrupt, InterruptExt};
8use embassy_hal_common::PeripheralRef; 8use embassy_hal_common::{Peripheral, PeripheralRef};
9use embassy_sync::waitqueue::AtomicWaker; 9use embassy_sync::waitqueue::AtomicWaker;
10 10
11use crate::dma::{Channel, Transfer}; 11use crate::dma::{Channel, Transfer, Word};
12use crate::gpio::sealed::Pin as SealedPin; 12use crate::gpio::sealed::Pin as SealedPin;
13use crate::gpio::{Drive, Pin, Pull, SlewRate}; 13use crate::gpio::{Drive, Pin, Pull, SlewRate};
14use crate::pac::dma::vals::{DataSize, TreqSel}; 14use crate::pac::dma::vals::TreqSel;
15use crate::pio::sealed::{PioInstance as _, SmInstance as _}; 15use crate::pio::sealed::PioInstance as _;
16use crate::{interrupt, pac, peripherals, RegExt}; 16use crate::{interrupt, pac, peripherals, RegExt};
17 17
18struct Wakers([AtomicWaker; 12]); 18struct Wakers([AtomicWaker; 12]);
@@ -119,10 +119,10 @@ impl<'d, PIO: PioInstance, SM: PioStateMachine + Unpin> Future for FifoOutFuture
119 if self.get_mut().sm.try_push_tx(value) { 119 if self.get_mut().sm.try_push_tx(value) {
120 Poll::Ready(()) 120 Poll::Ready(())
121 } else { 121 } else {
122 WAKERS[PIO::PIO_NO as usize].fifo_out()[SM::Sm::SM_NO as usize].register(cx.waker()); 122 WAKERS[PIO::PIO_NO as usize].fifo_out()[SM::SM as usize].register(cx.waker());
123 unsafe { 123 unsafe {
124 PIO::PIO.irqs(0).inte().write_set(|m| { 124 PIO::PIO.irqs(0).inte().write_set(|m| {
125 m.0 = TXNFULL_MASK << SM::Sm::SM_NO; 125 m.0 = TXNFULL_MASK << SM::SM;
126 }); 126 });
127 } 127 }
128 // debug!("Pending"); 128 // debug!("Pending");
@@ -135,7 +135,7 @@ impl<'d, PIO: PioInstance, SM: PioStateMachine + Unpin> Drop for FifoOutFuture<'
135 fn drop(&mut self) { 135 fn drop(&mut self) {
136 unsafe { 136 unsafe {
137 PIO::PIO.irqs(0).inte().write_clear(|m| { 137 PIO::PIO.irqs(0).inte().write_clear(|m| {
138 m.0 = TXNFULL_MASK << SM::Sm::SM_NO; 138 m.0 = TXNFULL_MASK << SM::SM;
139 }); 139 });
140 } 140 }
141 } 141 }
@@ -164,10 +164,10 @@ impl<'d, PIO: PioInstance, SM: PioStateMachine> Future for FifoInFuture<'d, PIO,
164 if let Some(v) = self.sm.try_pull_rx() { 164 if let Some(v) = self.sm.try_pull_rx() {
165 Poll::Ready(v) 165 Poll::Ready(v)
166 } else { 166 } else {
167 WAKERS[PIO::PIO_NO as usize].fifo_in()[SM::Sm::SM_NO as usize].register(cx.waker()); 167 WAKERS[PIO::PIO_NO as usize].fifo_in()[SM::SM].register(cx.waker());
168 unsafe { 168 unsafe {
169 PIO::PIO.irqs(0).inte().write_set(|m| { 169 PIO::PIO.irqs(0).inte().write_set(|m| {
170 m.0 = RXNEMPTY_MASK << SM::Sm::SM_NO; 170 m.0 = RXNEMPTY_MASK << SM::SM;
171 }); 171 });
172 } 172 }
173 //debug!("Pending"); 173 //debug!("Pending");
@@ -180,7 +180,7 @@ impl<'d, PIO: PioInstance, SM: PioStateMachine> Drop for FifoInFuture<'d, PIO, S
180 fn drop(&mut self) { 180 fn drop(&mut self) {
181 unsafe { 181 unsafe {
182 PIO::PIO.irqs(0).inte().write_clear(|m| { 182 PIO::PIO.irqs(0).inte().write_clear(|m| {
183 m.0 = RXNEMPTY_MASK << SM::Sm::SM_NO; 183 m.0 = RXNEMPTY_MASK << SM::SM;
184 }); 184 });
185 } 185 }
186 } 186 }
@@ -277,15 +277,14 @@ impl<PIO: PioInstance> PioPin<PIO> {
277 #[inline] 277 #[inline]
278 pub fn set_pull(&mut self, pull: Pull) { 278 pub fn set_pull(&mut self, pull: Pull) {
279 unsafe { 279 unsafe {
280 self.pad_ctrl().modify(|w| match pull { 280 self.pad_ctrl().modify(|w| {
281 Pull::Up => w.set_pue(true), 281 w.set_pue(pull == Pull::Up);
282 Pull::Down => w.set_pde(true), 282 w.set_pde(pull == Pull::Down);
283 Pull::None => {}
284 }); 283 });
285 } 284 }
286 } 285 }
287 286
288 /// Set the pin's pull. 287 /// Set the pin's schmitt trigger.
289 #[inline] 288 #[inline]
290 pub fn set_schmitt(&mut self, enable: bool) { 289 pub fn set_schmitt(&mut self, enable: bool) {
291 unsafe { 290 unsafe {
@@ -298,9 +297,11 @@ impl<PIO: PioInstance> PioPin<PIO> {
298 pub fn set_input_sync_bypass<'a>(&mut self, bypass: bool) { 297 pub fn set_input_sync_bypass<'a>(&mut self, bypass: bool) {
299 let mask = 1 << self.pin(); 298 let mask = 1 << self.pin();
300 unsafe { 299 unsafe {
301 PIO::PIO 300 if bypass {
302 .input_sync_bypass() 301 PIO::PIO.input_sync_bypass().write_set(|w| *w = mask);
303 .modify(|w| *w = if bypass { *w & !mask } else { *w | mask }); 302 } else {
303 PIO::PIO.input_sync_bypass().write_clear(|w| *w = mask);
304 }
304 } 305 }
305 } 306 }
306 307
@@ -315,16 +316,15 @@ impl<PIO: PioInstance> SealedPin for PioPin<PIO> {
315 } 316 }
316} 317}
317 318
318pub struct PioStateMachineInstance<PIO: PioInstance, SM: SmInstance> { 319pub struct PioStateMachineInstance<'d, PIO: PioInstance, const SM: usize> {
319 pio: PhantomData<PIO>, 320 pio: PhantomData<&'d PIO>,
320 sm: PhantomData<SM>,
321} 321}
322 322
323impl<PIO: PioInstance, SM: SmInstance> sealed::PioStateMachine for PioStateMachineInstance<PIO, SM> { 323impl<'d, PIO: PioInstance, const SM: usize> sealed::PioStateMachine for PioStateMachineInstance<'d, PIO, SM> {
324 type Pio = PIO; 324 type Pio = PIO;
325 type Sm = SM; 325 const SM: usize = SM;
326} 326}
327impl<PIO: PioInstance, SM: SmInstance> PioStateMachine for PioStateMachineInstance<PIO, SM> {} 327impl<'d, PIO: PioInstance, const SM: usize> PioStateMachine for PioStateMachineInstance<'d, PIO, SM> {}
328 328
329pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin { 329pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
330 fn pio_no(&self) -> u8 { 330 fn pio_no(&self) -> u8 {
@@ -332,60 +332,61 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
332 } 332 }
333 333
334 fn sm_no(&self) -> u8 { 334 fn sm_no(&self) -> u8 {
335 Self::Sm::SM_NO 335 Self::SM as u8
336 } 336 }
337 337
338 fn restart(&mut self) { 338 fn restart(&mut self) {
339 let mask = 1u8 << Self::SM;
339 unsafe { 340 unsafe {
340 Self::Pio::PIO 341 Self::Pio::PIO.ctrl().write_set(|w| w.set_sm_restart(mask));
341 .ctrl()
342 .modify(|w| w.set_sm_restart(1u8 << Self::Sm::SM_NO));
343 } 342 }
344 } 343 }
345 fn set_enable(&mut self, enable: bool) { 344 fn set_enable(&mut self, enable: bool) {
346 let mask = 1u8 << Self::Sm::SM_NO; 345 let mask = 1u8 << Self::SM;
347 unsafe { 346 unsafe {
348 Self::Pio::PIO 347 if enable {
349 .ctrl() 348 Self::Pio::PIO.ctrl().write_set(|w| w.set_sm_enable(mask));
350 .modify(|w| w.set_sm_enable((w.sm_enable() & !mask) | (if enable { mask } else { 0 }))); 349 } else {
350 Self::Pio::PIO.ctrl().write_clear(|w| w.set_sm_enable(mask));
351 }
351 } 352 }
352 } 353 }
353 354
354 fn is_enabled(&self) -> bool { 355 fn is_enabled(&self) -> bool {
355 unsafe { Self::Pio::PIO.ctrl().read().sm_enable() & (1u8 << Self::Sm::SM_NO) != 0 } 356 unsafe { Self::Pio::PIO.ctrl().read().sm_enable() & (1u8 << Self::SM) != 0 }
356 } 357 }
357 358
358 fn is_tx_empty(&self) -> bool { 359 fn is_tx_empty(&self) -> bool {
359 unsafe { Self::Pio::PIO.fstat().read().txempty() & (1u8 << Self::Sm::SM_NO) != 0 } 360 unsafe { Self::Pio::PIO.fstat().read().txempty() & (1u8 << Self::SM) != 0 }
360 } 361 }
361 fn is_tx_full(&self) -> bool { 362 fn is_tx_full(&self) -> bool {
362 unsafe { Self::Pio::PIO.fstat().read().txfull() & (1u8 << Self::Sm::SM_NO) != 0 } 363 unsafe { Self::Pio::PIO.fstat().read().txfull() & (1u8 << Self::SM) != 0 }
363 } 364 }
364 365
365 fn is_rx_empty(&self) -> bool { 366 fn is_rx_empty(&self) -> bool {
366 unsafe { Self::Pio::PIO.fstat().read().rxempty() & (1u8 << Self::Sm::SM_NO) != 0 } 367 unsafe { Self::Pio::PIO.fstat().read().rxempty() & (1u8 << Self::SM) != 0 }
367 } 368 }
368 fn is_rx_full(&self) -> bool { 369 fn is_rx_full(&self) -> bool {
369 unsafe { Self::Pio::PIO.fstat().read().rxfull() & (1u8 << Self::Sm::SM_NO) != 0 } 370 unsafe { Self::Pio::PIO.fstat().read().rxfull() & (1u8 << Self::SM) != 0 }
370 } 371 }
371 372
372 fn tx_level(&self) -> u8 { 373 fn tx_level(&self) -> u8 {
373 unsafe { 374 unsafe {
374 let flevel = Self::Pio::PIO.flevel().read().0; 375 let flevel = Self::Pio::PIO.flevel().read().0;
375 (flevel >> (Self::Sm::SM_NO * 8)) as u8 & 0x0f 376 (flevel >> (Self::SM * 8)) as u8 & 0x0f
376 } 377 }
377 } 378 }
378 379
379 fn rx_level(&self) -> u8 { 380 fn rx_level(&self) -> u8 {
380 unsafe { 381 unsafe {
381 let flevel = Self::Pio::PIO.flevel().read().0; 382 let flevel = Self::Pio::PIO.flevel().read().0;
382 (flevel >> (Self::Sm::SM_NO * 8 + 4)) as u8 & 0x0f 383 (flevel >> (Self::SM * 8 + 4)) as u8 & 0x0f
383 } 384 }
384 } 385 }
385 386
386 fn push_tx(&mut self, v: u32) { 387 fn push_tx(&mut self, v: u32) {
387 unsafe { 388 unsafe {
388 Self::Pio::PIO.txf(Self::Sm::SM_NO as usize).write_value(v); 389 Self::Pio::PIO.txf(Self::SM).write_value(v);
389 } 390 }
390 } 391 }
391 392
@@ -398,7 +399,7 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
398 } 399 }
399 400
400 fn pull_rx(&mut self) -> u32 { 401 fn pull_rx(&mut self) -> u32 {
401 unsafe { Self::Pio::PIO.rxf(Self::Sm::SM_NO as usize).read() } 402 unsafe { Self::Pio::PIO.rxf(Self::SM).read() }
402 } 403 }
403 404
404 fn try_pull_rx(&mut self) -> Option<u32> { 405 fn try_pull_rx(&mut self) -> Option<u32> {
@@ -410,73 +411,54 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
410 411
411 fn set_clkdiv(&mut self, div_x_256: u32) { 412 fn set_clkdiv(&mut self, div_x_256: u32) {
412 unsafe { 413 unsafe {
413 Self::Pio::PIO 414 Self::this_sm().clkdiv().write(|w| w.0 = div_x_256 << 8);
414 .sm(Self::Sm::SM_NO as usize)
415 .clkdiv()
416 .write(|w| w.0 = div_x_256 << 8);
417 } 415 }
418 } 416 }
419 417
420 fn get_clkdiv(&self) -> u32 { 418 fn get_clkdiv(&self) -> u32 {
421 unsafe { Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).clkdiv().read().0 >> 8 } 419 unsafe { Self::this_sm().clkdiv().read().0 >> 8 }
422 } 420 }
423 421
424 fn clkdiv_restart(&mut self) { 422 fn clkdiv_restart(&mut self) {
423 let mask = 1u8 << Self::SM;
425 unsafe { 424 unsafe {
426 Self::Pio::PIO 425 Self::Pio::PIO.ctrl().write_set(|w| w.set_clkdiv_restart(mask));
427 .ctrl()
428 .modify(|w| w.set_clkdiv_restart(1u8 << Self::Sm::SM_NO));
429 } 426 }
430 } 427 }
431 428
432 fn set_side_enable(&self, enable: bool) { 429 fn set_side_enable(&self, enable: bool) {
433 unsafe { 430 unsafe {
434 Self::Pio::PIO 431 Self::this_sm().execctrl().modify(|w| w.set_side_en(enable));
435 .sm(Self::Sm::SM_NO as usize)
436 .execctrl()
437 .modify(|w| w.set_side_en(enable));
438 } 432 }
439 } 433 }
440 434
441 fn is_side_enabled(&self) -> bool { 435 fn is_side_enabled(&self) -> bool {
442 unsafe { Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).execctrl().read().side_en() } 436 unsafe { Self::this_sm().execctrl().read().side_en() }
443 } 437 }
444 438
445 fn set_side_pindir(&mut self, pindir: bool) { 439 fn set_side_pindir(&mut self, pindir: bool) {
446 unsafe { 440 unsafe {
447 Self::Pio::PIO 441 Self::this_sm().execctrl().modify(|w| w.set_side_pindir(pindir));
448 .sm(Self::Sm::SM_NO as usize)
449 .execctrl()
450 .modify(|w| w.set_side_pindir(pindir));
451 } 442 }
452 } 443 }
453 444
454 fn is_side_pindir(&self) -> bool { 445 fn is_side_pindir(&self) -> bool {
455 unsafe { 446 unsafe { Self::this_sm().execctrl().read().side_pindir() }
456 Self::Pio::PIO
457 .sm(Self::Sm::SM_NO as usize)
458 .execctrl()
459 .read()
460 .side_pindir()
461 }
462 } 447 }
463 448
464 fn set_jmp_pin(&mut self, pin: u8) { 449 fn set_jmp_pin(&mut self, pin: u8) {
465 unsafe { 450 unsafe {
466 Self::Pio::PIO 451 Self::this_sm().execctrl().modify(|w| w.set_jmp_pin(pin));
467 .sm(Self::Sm::SM_NO as usize)
468 .execctrl()
469 .modify(|w| w.set_jmp_pin(pin));
470 } 452 }
471 } 453 }
472 454
473 fn get_jmp_pin(&mut self) -> u8 { 455 fn get_jmp_pin(&mut self) -> u8 {
474 unsafe { Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).execctrl().read().jmp_pin() } 456 unsafe { Self::this_sm().execctrl().read().jmp_pin() }
475 } 457 }
476 458
477 fn set_wrap(&self, source: u8, target: u8) { 459 fn set_wrap(&self, source: u8, target: u8) {
478 unsafe { 460 unsafe {
479 Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).execctrl().modify(|w| { 461 Self::this_sm().execctrl().modify(|w| {
480 w.set_wrap_top(source); 462 w.set_wrap_top(source);
481 w.set_wrap_bottom(target) 463 w.set_wrap_bottom(target)
482 }); 464 });
@@ -486,7 +468,7 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
486 /// Get wrapping addresses. Returns (source, target). 468 /// Get wrapping addresses. Returns (source, target).
487 fn get_wrap(&self) -> (u8, u8) { 469 fn get_wrap(&self) -> (u8, u8) {
488 unsafe { 470 unsafe {
489 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).execctrl().read(); 471 let r = Self::this_sm().execctrl().read();
490 (r.wrap_top(), r.wrap_bottom()) 472 (r.wrap_top(), r.wrap_bottom())
491 } 473 }
492 } 474 }
@@ -498,7 +480,7 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
498 FifoJoin::TxOnly => (false, true), 480 FifoJoin::TxOnly => (false, true),
499 }; 481 };
500 unsafe { 482 unsafe {
501 Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).shiftctrl().modify(|w| { 483 Self::this_sm().shiftctrl().modify(|w| {
502 w.set_fjoin_rx(rx); 484 w.set_fjoin_rx(rx);
503 w.set_fjoin_tx(tx) 485 w.set_fjoin_tx(tx)
504 }); 486 });
@@ -506,7 +488,7 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
506 } 488 }
507 fn get_fifo_join(&self) -> FifoJoin { 489 fn get_fifo_join(&self) -> FifoJoin {
508 unsafe { 490 unsafe {
509 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).shiftctrl().read(); 491 let r = Self::this_sm().shiftctrl().read();
510 // Ignores the invalid state when both bits are set 492 // Ignores the invalid state when both bits are set
511 if r.fjoin_rx() { 493 if r.fjoin_rx() {
512 FifoJoin::RxOnly 494 FifoJoin::RxOnly
@@ -521,7 +503,7 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
521 fn clear_fifos(&mut self) { 503 fn clear_fifos(&mut self) {
522 // Toggle FJOIN_RX to flush FIFOs 504 // Toggle FJOIN_RX to flush FIFOs
523 unsafe { 505 unsafe {
524 let shiftctrl = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).shiftctrl(); 506 let shiftctrl = Self::this_sm().shiftctrl();
525 shiftctrl.modify(|w| { 507 shiftctrl.modify(|w| {
526 w.set_fjoin_rx(!w.fjoin_rx()); 508 w.set_fjoin_rx(!w.fjoin_rx());
527 }); 509 });
@@ -533,51 +515,33 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
533 515
534 fn set_pull_threshold(&mut self, threshold: u8) { 516 fn set_pull_threshold(&mut self, threshold: u8) {
535 unsafe { 517 unsafe {
536 Self::Pio::PIO 518 Self::this_sm().shiftctrl().modify(|w| w.set_pull_thresh(threshold));
537 .sm(Self::Sm::SM_NO as usize)
538 .shiftctrl()
539 .modify(|w| w.set_pull_thresh(threshold));
540 } 519 }
541 } 520 }
542 521
543 fn get_pull_threshold(&self) -> u8 { 522 fn get_pull_threshold(&self) -> u8 {
544 unsafe { 523 unsafe { Self::this_sm().shiftctrl().read().pull_thresh() }
545 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).shiftctrl().read();
546 r.pull_thresh()
547 }
548 } 524 }
549 fn set_push_threshold(&mut self, threshold: u8) { 525 fn set_push_threshold(&mut self, threshold: u8) {
550 unsafe { 526 unsafe {
551 Self::Pio::PIO 527 Self::this_sm().shiftctrl().modify(|w| w.set_push_thresh(threshold));
552 .sm(Self::Sm::SM_NO as usize)
553 .shiftctrl()
554 .modify(|w| w.set_push_thresh(threshold));
555 } 528 }
556 } 529 }
557 530
558 fn get_push_threshold(&self) -> u8 { 531 fn get_push_threshold(&self) -> u8 {
559 unsafe { 532 unsafe { Self::this_sm().shiftctrl().read().push_thresh() }
560 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).shiftctrl().read();
561 r.push_thresh()
562 }
563 } 533 }
564 534
565 fn set_out_shift_dir(&mut self, dir: ShiftDirection) { 535 fn set_out_shift_dir(&mut self, dir: ShiftDirection) {
566 unsafe { 536 unsafe {
567 Self::Pio::PIO 537 Self::this_sm()
568 .sm(Self::Sm::SM_NO as usize)
569 .shiftctrl() 538 .shiftctrl()
570 .modify(|w| w.set_out_shiftdir(dir == ShiftDirection::Right)); 539 .modify(|w| w.set_out_shiftdir(dir == ShiftDirection::Right));
571 } 540 }
572 } 541 }
573 fn get_out_shiftdir(&self) -> ShiftDirection { 542 fn get_out_shiftdir(&self) -> ShiftDirection {
574 unsafe { 543 unsafe {
575 if Self::Pio::PIO 544 if Self::this_sm().shiftctrl().read().out_shiftdir() {
576 .sm(Self::Sm::SM_NO as usize)
577 .shiftctrl()
578 .read()
579 .out_shiftdir()
580 {
581 ShiftDirection::Right 545 ShiftDirection::Right
582 } else { 546 } else {
583 ShiftDirection::Left 547 ShiftDirection::Left
@@ -587,20 +551,14 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
587 551
588 fn set_in_shift_dir(&mut self, dir: ShiftDirection) { 552 fn set_in_shift_dir(&mut self, dir: ShiftDirection) {
589 unsafe { 553 unsafe {
590 Self::Pio::PIO 554 Self::this_sm()
591 .sm(Self::Sm::SM_NO as usize)
592 .shiftctrl() 555 .shiftctrl()
593 .modify(|w| w.set_in_shiftdir(dir == ShiftDirection::Right)); 556 .modify(|w| w.set_in_shiftdir(dir == ShiftDirection::Right));
594 } 557 }
595 } 558 }
596 fn get_in_shiftdir(&self) -> ShiftDirection { 559 fn get_in_shiftdir(&self) -> ShiftDirection {
597 unsafe { 560 unsafe {
598 if Self::Pio::PIO 561 if Self::this_sm().shiftctrl().read().in_shiftdir() {
599 .sm(Self::Sm::SM_NO as usize)
600 .shiftctrl()
601 .read()
602 .in_shiftdir()
603 {
604 ShiftDirection::Right 562 ShiftDirection::Right
605 } else { 563 } else {
606 ShiftDirection::Left 564 ShiftDirection::Left
@@ -610,76 +568,46 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
610 568
611 fn set_autopull(&mut self, auto: bool) { 569 fn set_autopull(&mut self, auto: bool) {
612 unsafe { 570 unsafe {
613 Self::Pio::PIO 571 Self::this_sm().shiftctrl().modify(|w| w.set_autopull(auto));
614 .sm(Self::Sm::SM_NO as usize)
615 .shiftctrl()
616 .modify(|w| w.set_autopull(auto));
617 } 572 }
618 } 573 }
619 574
620 fn is_autopull(&self) -> bool { 575 fn is_autopull(&self) -> bool {
621 unsafe { 576 unsafe { Self::this_sm().shiftctrl().read().autopull() }
622 Self::Pio::PIO
623 .sm(Self::Sm::SM_NO as usize)
624 .shiftctrl()
625 .read()
626 .autopull()
627 }
628 } 577 }
629 578
630 fn set_autopush(&mut self, auto: bool) { 579 fn set_autopush(&mut self, auto: bool) {
631 unsafe { 580 unsafe {
632 Self::Pio::PIO 581 Self::this_sm().shiftctrl().modify(|w| w.set_autopush(auto));
633 .sm(Self::Sm::SM_NO as usize)
634 .shiftctrl()
635 .modify(|w| w.set_autopush(auto));
636 } 582 }
637 } 583 }
638 584
639 fn is_autopush(&self) -> bool { 585 fn is_autopush(&self) -> bool {
640 unsafe { 586 unsafe { Self::this_sm().shiftctrl().read().autopush() }
641 Self::Pio::PIO
642 .sm(Self::Sm::SM_NO as usize)
643 .shiftctrl()
644 .read()
645 .autopush()
646 }
647 } 587 }
648 588
649 fn get_addr(&self) -> u8 { 589 fn get_addr(&self) -> u8 {
650 unsafe { 590 unsafe { Self::this_sm().addr().read().addr() }
651 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).addr().read();
652 r.addr()
653 }
654 } 591 }
655 fn set_sideset_count(&mut self, count: u8) { 592 fn set_sideset_count(&mut self, count: u8) {
656 unsafe { 593 unsafe {
657 Self::Pio::PIO 594 Self::this_sm().pinctrl().modify(|w| w.set_sideset_count(count));
658 .sm(Self::Sm::SM_NO as usize)
659 .pinctrl()
660 .modify(|w| w.set_sideset_count(count));
661 } 595 }
662 } 596 }
663 597
664 fn get_sideset_count(&self) -> u8 { 598 fn get_sideset_count(&self) -> u8 {
665 unsafe { 599 unsafe { Self::this_sm().pinctrl().read().sideset_count() }
666 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().read();
667 r.sideset_count()
668 }
669 } 600 }
670 601
671 fn set_sideset_base_pin(&mut self, base_pin: &PioPin<Self::Pio>) { 602 fn set_sideset_base_pin(&mut self, base_pin: &PioPin<Self::Pio>) {
672 unsafe { 603 unsafe {
673 Self::Pio::PIO 604 Self::this_sm().pinctrl().modify(|w| w.set_sideset_base(base_pin.pin()));
674 .sm(Self::Sm::SM_NO as usize)
675 .pinctrl()
676 .modify(|w| w.set_sideset_base(base_pin.pin()));
677 } 605 }
678 } 606 }
679 607
680 fn get_sideset_base(&self) -> u8 { 608 fn get_sideset_base(&self) -> u8 {
681 unsafe { 609 unsafe {
682 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().read(); 610 let r = Self::this_sm().pinctrl().read();
683 r.sideset_base() 611 r.sideset_base()
684 } 612 }
685 } 613 }
@@ -688,7 +616,7 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
688 fn set_set_range(&mut self, base: u8, count: u8) { 616 fn set_set_range(&mut self, base: u8, count: u8) {
689 assert!(base + count < 32); 617 assert!(base + count < 32);
690 unsafe { 618 unsafe {
691 Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().modify(|w| { 619 Self::this_sm().pinctrl().modify(|w| {
692 w.set_set_base(base); 620 w.set_set_base(base);
693 w.set_set_count(count) 621 w.set_set_count(count)
694 }); 622 });
@@ -698,23 +626,20 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
698 /// Get the range of out pins affected by a set instruction. Returns (base, count). 626 /// Get the range of out pins affected by a set instruction. Returns (base, count).
699 fn get_set_range(&self) -> (u8, u8) { 627 fn get_set_range(&self) -> (u8, u8) {
700 unsafe { 628 unsafe {
701 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().read(); 629 let r = Self::this_sm().pinctrl().read();
702 (r.set_base(), r.set_count()) 630 (r.set_base(), r.set_count())
703 } 631 }
704 } 632 }
705 633
706 fn set_in_base_pin(&mut self, base: &PioPin<Self::Pio>) { 634 fn set_in_base_pin(&mut self, base: &PioPin<Self::Pio>) {
707 unsafe { 635 unsafe {
708 Self::Pio::PIO 636 Self::this_sm().pinctrl().modify(|w| w.set_in_base(base.pin()));
709 .sm(Self::Sm::SM_NO as usize)
710 .pinctrl()
711 .modify(|w| w.set_in_base(base.pin()));
712 } 637 }
713 } 638 }
714 639
715 fn get_in_base(&self) -> u8 { 640 fn get_in_base(&self) -> u8 {
716 unsafe { 641 unsafe {
717 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().read(); 642 let r = Self::this_sm().pinctrl().read();
718 r.in_base() 643 r.in_base()
719 } 644 }
720 } 645 }
@@ -722,7 +647,7 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
722 fn set_out_range(&mut self, base: u8, count: u8) { 647 fn set_out_range(&mut self, base: u8, count: u8) {
723 assert!(base + count < 32); 648 assert!(base + count < 32);
724 unsafe { 649 unsafe {
725 Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().modify(|w| { 650 Self::this_sm().pinctrl().modify(|w| {
726 w.set_out_base(base); 651 w.set_out_base(base);
727 w.set_out_count(count) 652 w.set_out_count(count)
728 }); 653 });
@@ -732,7 +657,7 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
732 /// Get the range of out pins affected by a set instruction. Returns (base, count). 657 /// Get the range of out pins affected by a set instruction. Returns (base, count).
733 fn get_out_range(&self) -> (u8, u8) { 658 fn get_out_range(&self) -> (u8, u8) {
734 unsafe { 659 unsafe {
735 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().read(); 660 let r = Self::this_sm().pinctrl().read();
736 (r.out_base(), r.out_count()) 661 (r.out_base(), r.out_count())
737 } 662 }
738 } 663 }
@@ -760,15 +685,12 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
760 } 685 }
761 686
762 fn get_current_instr() -> u32 { 687 fn get_current_instr() -> u32 {
763 unsafe { Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).instr().read().0 } 688 unsafe { Self::this_sm().instr().read().0 }
764 } 689 }
765 690
766 fn exec_instr(&mut self, instr: u16) { 691 fn exec_instr(&mut self, instr: u16) {
767 unsafe { 692 unsafe {
768 Self::Pio::PIO 693 Self::this_sm().instr().write(|w| w.set_instr(instr));
769 .sm(Self::Sm::SM_NO as usize)
770 .instr()
771 .write(|w| w.set_instr(instr));
772 } 694 }
773 } 695 }
774 696
@@ -787,8 +709,8 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
787 fn has_tx_stalled(&self) -> bool { 709 fn has_tx_stalled(&self) -> bool {
788 unsafe { 710 unsafe {
789 let fdebug = Self::Pio::PIO.fdebug(); 711 let fdebug = Self::Pio::PIO.fdebug();
790 let ret = fdebug.read().txstall() & (1 << Self::Sm::SM_NO) != 0; 712 let ret = fdebug.read().txstall() & (1 << Self::SM) != 0;
791 fdebug.write(|w| w.set_txstall(1 << Self::Sm::SM_NO)); 713 fdebug.write(|w| w.set_txstall(1 << Self::SM));
792 ret 714 ret
793 } 715 }
794 } 716 }
@@ -796,8 +718,8 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
796 fn has_tx_overflowed(&self) -> bool { 718 fn has_tx_overflowed(&self) -> bool {
797 unsafe { 719 unsafe {
798 let fdebug = Self::Pio::PIO.fdebug(); 720 let fdebug = Self::Pio::PIO.fdebug();
799 let ret = fdebug.read().txover() & (1 << Self::Sm::SM_NO) != 0; 721 let ret = fdebug.read().txover() & (1 << Self::SM) != 0;
800 fdebug.write(|w| w.set_txover(1 << Self::Sm::SM_NO)); 722 fdebug.write(|w| w.set_txover(1 << Self::SM));
801 ret 723 ret
802 } 724 }
803 } 725 }
@@ -805,8 +727,8 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
805 fn has_rx_stalled(&self) -> bool { 727 fn has_rx_stalled(&self) -> bool {
806 unsafe { 728 unsafe {
807 let fdebug = Self::Pio::PIO.fdebug(); 729 let fdebug = Self::Pio::PIO.fdebug();
808 let ret = fdebug.read().rxstall() & (1 << Self::Sm::SM_NO) != 0; 730 let ret = fdebug.read().rxstall() & (1 << Self::SM) != 0;
809 fdebug.write(|w| w.set_rxstall(1 << Self::Sm::SM_NO)); 731 fdebug.write(|w| w.set_rxstall(1 << Self::SM));
810 ret 732 ret
811 } 733 }
812 } 734 }
@@ -814,25 +736,25 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
814 fn has_rx_underflowed(&self) -> bool { 736 fn has_rx_underflowed(&self) -> bool {
815 unsafe { 737 unsafe {
816 let fdebug = Self::Pio::PIO.fdebug(); 738 let fdebug = Self::Pio::PIO.fdebug();
817 let ret = fdebug.read().rxunder() & (1 << Self::Sm::SM_NO) != 0; 739 let ret = fdebug.read().rxunder() & (1 << Self::SM) != 0;
818 fdebug.write(|w| w.set_rxunder(1 << Self::Sm::SM_NO)); 740 fdebug.write(|w| w.set_rxunder(1 << Self::SM));
819 ret 741 ret
820 } 742 }
821 } 743 }
822 744
823 fn dma_push<'a, C: Channel>(&'a self, ch: PeripheralRef<'a, C>, data: &'a [u32]) -> Transfer<'a, C> { 745 fn dma_push<'a, C: Channel, W: Word>(&'a self, ch: PeripheralRef<'a, C>, data: &'a [W]) -> Transfer<'a, C> {
824 unsafe { 746 unsafe {
825 let pio_no = Self::Pio::PIO_NO; 747 let pio_no = Self::Pio::PIO_NO;
826 let sm_no = Self::Sm::SM_NO; 748 let sm_no = Self::SM;
827 let p = ch.regs(); 749 let p = ch.regs();
828 p.read_addr().write_value(data.as_ptr() as u32); 750 p.read_addr().write_value(data.as_ptr() as u32);
829 p.write_addr() 751 p.write_addr().write_value(Self::Pio::PIO.txf(sm_no).ptr() as u32);
830 .write_value(Self::Pio::PIO.txf(sm_no as usize).ptr() as u32);
831 p.trans_count().write_value(data.len() as u32); 752 p.trans_count().write_value(data.len() as u32);
753 compiler_fence(Ordering::SeqCst);
832 p.ctrl_trig().write(|w| { 754 p.ctrl_trig().write(|w| {
833 // Set TX DREQ for this statemachine 755 // Set TX DREQ for this statemachine
834 w.set_treq_sel(TreqSel(pio_no * 8 + sm_no)); 756 w.set_treq_sel(TreqSel(pio_no * 8 + sm_no as u8));
835 w.set_data_size(DataSize::SIZE_WORD); 757 w.set_data_size(W::size());
836 w.set_chain_to(ch.number()); 758 w.set_chain_to(ch.number());
837 w.set_incr_read(true); 759 w.set_incr_read(true);
838 w.set_incr_write(false); 760 w.set_incr_write(false);
@@ -843,19 +765,19 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
843 Transfer::new(ch) 765 Transfer::new(ch)
844 } 766 }
845 767
846 fn dma_pull<'a, C: Channel>(&'a self, ch: PeripheralRef<'a, C>, data: &'a mut [u32]) -> Transfer<'a, C> { 768 fn dma_pull<'a, C: Channel, W: Word>(&'a self, ch: PeripheralRef<'a, C>, data: &'a mut [W]) -> Transfer<'a, C> {
847 unsafe { 769 unsafe {
848 let pio_no = Self::Pio::PIO_NO; 770 let pio_no = Self::Pio::PIO_NO;
849 let sm_no = Self::Sm::SM_NO; 771 let sm_no = Self::SM;
850 let p = ch.regs(); 772 let p = ch.regs();
851 p.write_addr().write_value(data.as_ptr() as u32); 773 p.write_addr().write_value(data.as_ptr() as u32);
852 p.read_addr() 774 p.read_addr().write_value(Self::Pio::PIO.rxf(sm_no).ptr() as u32);
853 .write_value(Self::Pio::PIO.rxf(sm_no as usize).ptr() as u32);
854 p.trans_count().write_value(data.len() as u32); 775 p.trans_count().write_value(data.len() as u32);
776 compiler_fence(Ordering::SeqCst);
855 p.ctrl_trig().write(|w| { 777 p.ctrl_trig().write(|w| {
856 // Set TX DREQ for this statemachine 778 // Set RX DREQ for this statemachine
857 w.set_treq_sel(TreqSel(pio_no * 8 + sm_no + 4)); 779 w.set_treq_sel(TreqSel(pio_no * 8 + sm_no as u8 + 4));
858 w.set_data_size(DataSize::SIZE_WORD); 780 w.set_data_size(W::size());
859 w.set_chain_to(ch.number()); 781 w.set_chain_to(ch.number());
860 w.set_incr_read(false); 782 w.set_incr_read(false);
861 w.set_incr_write(true); 783 w.set_incr_write(true);
@@ -867,21 +789,18 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
867 } 789 }
868} 790}
869 791
870pub struct PioCommonInstance<PIO: PioInstance> { 792pub struct PioCommon<'d, PIO: PioInstance> {
871 instructions_used: u32, 793 instructions_used: u32,
872 pio: PhantomData<PIO>, 794 pio: PhantomData<&'d PIO>,
873} 795}
874 796
875pub struct PioInstanceMemory<PIO: PioInstance> { 797pub struct PioInstanceMemory<'d, PIO: PioInstance> {
876 used_mask: u32, 798 used_mask: u32,
877 pio: PhantomData<PIO>, 799 pio: PhantomData<&'d PIO>,
878} 800}
879 801
880impl<PIO: PioInstance> sealed::PioCommon for PioCommonInstance<PIO> { 802impl<'d, PIO: PioInstance> PioCommon<'d, PIO> {
881 type Pio = PIO; 803 pub fn write_instr<I>(&mut self, start: usize, instrs: I) -> PioInstanceMemory<'d, PIO>
882}
883impl<PIO: PioInstance> PioCommon for PioCommonInstance<PIO> {
884 fn write_instr<I>(&mut self, start: usize, instrs: I) -> PioInstanceMemory<Self::Pio>
885 where 804 where
886 I: Iterator<Item = u16>, 805 I: Iterator<Item = u16>,
887 { 806 {
@@ -908,66 +827,50 @@ impl<PIO: PioInstance> PioCommon for PioCommonInstance<PIO> {
908 } 827 }
909 } 828 }
910 829
911 fn free_instr(&mut self, instrs: PioInstanceMemory<Self::Pio>) { 830 // TODO make instruction memory that is currently in use unfreeable
831 pub fn free_instr(&mut self, instrs: PioInstanceMemory<PIO>) {
912 self.instructions_used &= !instrs.used_mask; 832 self.instructions_used &= !instrs.used_mask;
913 } 833 }
914}
915
916pub trait PioCommon: sealed::PioCommon + Sized {
917 fn write_instr<I>(&mut self, start: usize, instrs: I) -> PioInstanceMemory<Self::Pio>
918 where
919 I: Iterator<Item = u16>;
920 834
921 // TODO make instruction memory that is currently in use unfreeable 835 pub fn is_irq_set(&self, irq_no: u8) -> bool {
922 fn free_instr(&mut self, instrs: PioInstanceMemory<Self::Pio>);
923
924 fn is_irq_set(&self, irq_no: u8) -> bool {
925 assert!(irq_no < 8); 836 assert!(irq_no < 8);
926 unsafe { 837 unsafe {
927 let irq_flags = Self::Pio::PIO.irq(); 838 let irq_flags = PIO::PIO.irq();
928 irq_flags.read().0 & (1 << irq_no) != 0 839 irq_flags.read().0 & (1 << irq_no) != 0
929 } 840 }
930 } 841 }
931 842
932 fn clear_irq(&mut self, irq_no: usize) { 843 pub fn clear_irq(&mut self, irq_no: usize) {
933 assert!(irq_no < 8); 844 assert!(irq_no < 8);
934 unsafe { Self::Pio::PIO.irq().write(|w| w.set_irq(1 << irq_no)) } 845 unsafe { PIO::PIO.irq().write(|w| w.set_irq(1 << irq_no)) }
935 } 846 }
936 847
937 fn clear_irqs(&mut self, mask: u8) { 848 pub fn clear_irqs(&mut self, mask: u8) {
938 unsafe { Self::Pio::PIO.irq().write(|w| w.set_irq(mask)) } 849 unsafe { PIO::PIO.irq().write(|w| w.set_irq(mask)) }
939 } 850 }
940 851
941 fn force_irq(&mut self, irq_no: usize) { 852 pub fn force_irq(&mut self, irq_no: usize) {
942 assert!(irq_no < 8); 853 assert!(irq_no < 8);
943 unsafe { Self::Pio::PIO.irq_force().write(|w| w.set_irq_force(1 << irq_no)) } 854 unsafe { PIO::PIO.irq_force().write(|w| w.set_irq_force(1 << irq_no)) }
944 } 855 }
945 856
946 fn set_input_sync_bypass<'a>(&'a mut self, bypass: u32, mask: u32) { 857 pub fn set_input_sync_bypass<'a>(&'a mut self, bypass: u32, mask: u32) {
947 unsafe { 858 unsafe {
948 Self::Pio::PIO 859 // this can interfere with per-pin bypass functions. splitting the
949 .input_sync_bypass() 860 // modification is going to be fine since nothing that relies on
950 .modify(|w| *w = (*w & !mask) | (bypass & mask)); 861 // it can reasonably run before we finish.
862 PIO::PIO.input_sync_bypass().write_set(|w| *w = mask & bypass);
863 PIO::PIO.input_sync_bypass().write_clear(|w| *w = mask & !bypass);
951 } 864 }
952 } 865 }
953 866
954 fn get_input_sync_bypass(&self) -> u32 { 867 pub fn get_input_sync_bypass(&self) -> u32 {
955 unsafe { Self::Pio::PIO.input_sync_bypass().read() } 868 unsafe { PIO::PIO.input_sync_bypass().read() }
956 } 869 }
957 870
958 fn make_pio_pin(&self, pin: impl Pin) -> PioPin<Self::Pio> { 871 pub fn make_pio_pin(&self, pin: impl Pin) -> PioPin<PIO> {
959 unsafe { 872 unsafe {
960 pin.io().ctrl().write(|w| { 873 pin.io().ctrl().write(|w| w.set_funcsel(PIO::FUNCSEL.0));
961 w.set_funcsel(
962 if Self::Pio::PIO_NO == 1 {
963 pac::io::vals::Gpio0ctrlFuncsel::PIO1_0
964 } else {
965 // PIO == 0
966 pac::io::vals::Gpio0ctrlFuncsel::PIO0_0
967 }
968 .0,
969 );
970 });
971 } 874 }
972 PioPin { 875 PioPin {
973 pin_bank: pin.pin_bank(), 876 pin_bank: pin.pin_bank(),
@@ -976,112 +879,63 @@ pub trait PioCommon: sealed::PioCommon + Sized {
976 } 879 }
977} 880}
978 881
979// Identifies a specific state machine inside a PIO device 882pub struct Pio<'d, PIO: PioInstance> {
980pub struct SmInstanceBase<const SM_NO: u8> {} 883 pub common: PioCommon<'d, PIO>,
981 884 pub sm0: PioStateMachineInstance<'d, PIO, 0>,
982pub trait SmInstance: sealed::SmInstance + Unpin {} 885 pub sm1: PioStateMachineInstance<'d, PIO, 1>,
983 886 pub sm2: PioStateMachineInstance<'d, PIO, 2>,
984impl<const SM_NO: u8> sealed::SmInstance for SmInstanceBase<SM_NO> { 887 pub sm3: PioStateMachineInstance<'d, PIO, 3>,
985 const SM_NO: u8 = SM_NO;
986} 888}
987impl<const SM_NO: u8> SmInstance for SmInstanceBase<SM_NO> {}
988
989pub trait PioPeripheral: sealed::PioPeripheral + Sized {
990 fn pio(&self) -> u8 {
991 Self::Pio::PIO_NO
992 }
993 889
994 fn split( 890impl<'d, PIO: PioInstance> Pio<'d, PIO> {
995 self, 891 pub fn new(_pio: impl Peripheral<P = PIO> + 'd) -> Self {
996 ) -> ( 892 Self {
997 PioCommonInstance<Self::Pio>, 893 common: PioCommon {
998 PioStateMachineInstance<Self::Pio, SmInstanceBase<0>>,
999 PioStateMachineInstance<Self::Pio, SmInstanceBase<1>>,
1000 PioStateMachineInstance<Self::Pio, SmInstanceBase<2>>,
1001 PioStateMachineInstance<Self::Pio, SmInstanceBase<3>>,
1002 ) {
1003 (
1004 PioCommonInstance {
1005 instructions_used: 0, 894 instructions_used: 0,
1006 pio: PhantomData::default(), 895 pio: PhantomData,
1007 }, 896 },
1008 PioStateMachineInstance { 897 sm0: PioStateMachineInstance { pio: PhantomData },
1009 sm: PhantomData::default(), 898 sm1: PioStateMachineInstance { pio: PhantomData },
1010 pio: PhantomData::default(), 899 sm2: PioStateMachineInstance { pio: PhantomData },
1011 }, 900 sm3: PioStateMachineInstance { pio: PhantomData },
1012 PioStateMachineInstance { 901 }
1013 sm: PhantomData::default(),
1014 pio: PhantomData::default(),
1015 },
1016 PioStateMachineInstance {
1017 sm: PhantomData::default(),
1018 pio: PhantomData::default(),
1019 },
1020 PioStateMachineInstance {
1021 sm: PhantomData::default(),
1022 pio: PhantomData::default(),
1023 },
1024 )
1025 } 902 }
1026} 903}
1027 904
1028mod sealed { 905pub trait PioInstance: sealed::PioInstance + Sized + Unpin {
1029 pub trait PioInstance { 906 fn pio(&self) -> u8 {
1030 const PIO_NO: u8; 907 Self::PIO_NO
1031 const PIO: &'static crate::pac::pio::Pio;
1032 }
1033
1034 pub trait PioCommon {
1035 type Pio: super::PioInstance;
1036 } 908 }
909}
1037 910
911mod sealed {
1038 pub trait PioStateMachine { 912 pub trait PioStateMachine {
1039 type Pio: super::PioInstance; 913 type Pio: super::PioInstance;
1040 type Sm: super::SmInstance; 914 const SM: usize;
1041 }
1042 915
1043 pub trait SmInstance { 916 #[inline(always)]
1044 const SM_NO: u8; 917 fn this_sm() -> crate::pac::pio::StateMachine {
918 Self::Pio::PIO.sm(Self::SM as usize)
919 }
1045 } 920 }
1046 921
1047 pub trait PioPeripheral { 922 pub trait PioInstance {
1048 type Pio: super::PioInstance; 923 const PIO_NO: u8;
924 const PIO: &'static crate::pac::pio::Pio;
925 const FUNCSEL: crate::pac::io::vals::Gpio0ctrlFuncsel;
1049 } 926 }
1050} 927}
1051 928
1052// Identifies a specific PIO device 929macro_rules! impl_pio {
1053pub struct PioInstanceBase<const PIO_NO: u8> {} 930 ($name:ident, $pio:expr, $pac:ident, $funcsel:ident) => {
1054 931 impl sealed::PioInstance for peripherals::$name {
1055pub trait PioInstance: sealed::PioInstance + Unpin {} 932 const PIO_NO: u8 = $pio;
1056 933 const PIO: &'static pac::pio::Pio = &pac::$pac;
1057impl sealed::PioInstance for PioInstanceBase<0> { 934 const FUNCSEL: pac::io::vals::Gpio0ctrlFuncsel = pac::io::vals::Gpio0ctrlFuncsel::$funcsel;
1058 const PIO_NO: u8 = 0;
1059 const PIO: &'static pac::pio::Pio = &pac::PIO0;
1060}
1061impl PioInstance for PioInstanceBase<0> {}
1062
1063impl sealed::PioInstance for PioInstanceBase<1> {
1064 const PIO_NO: u8 = 1;
1065 const PIO: &'static pac::pio::Pio = &pac::PIO1;
1066}
1067impl PioInstance for PioInstanceBase<1> {}
1068
1069pub type Pio0 = PioInstanceBase<0>;
1070pub type Pio1 = PioInstanceBase<1>;
1071
1072pub type Sm0 = SmInstanceBase<0>;
1073pub type Sm1 = SmInstanceBase<1>;
1074pub type Sm2 = SmInstanceBase<2>;
1075pub type Sm3 = SmInstanceBase<3>;
1076
1077macro_rules! impl_pio_sm {
1078 ($name:ident, $pio:expr) => {
1079 impl sealed::PioPeripheral for peripherals::$name {
1080 type Pio = PioInstanceBase<$pio>;
1081 } 935 }
1082 impl PioPeripheral for peripherals::$name {} 936 impl PioInstance for peripherals::$name {}
1083 }; 937 };
1084} 938}
1085 939
1086impl_pio_sm!(PIO0, 0); 940impl_pio!(PIO0, 0, PIO0, PIO0_0);
1087impl_pio_sm!(PIO1, 1); 941impl_pio!(PIO1, 1, PIO1, PIO1_0);
diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs
index 1b075b8fd..5fea7034b 100644
--- a/examples/rp/src/bin/pio_async.rs
+++ b/examples/rp/src/bin/pio_async.rs
@@ -4,15 +4,13 @@
4use defmt::info; 4use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_rp::gpio::{AnyPin, Pin}; 6use embassy_rp::gpio::{AnyPin, Pin};
7use embassy_rp::pio::{ 7use embassy_rp::peripherals::PIO0;
8 Pio0, PioCommon, PioCommonInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0, 8use embassy_rp::pio::{Pio, PioCommon, PioStateMachine, PioStateMachineInstance, ShiftDirection};
9 Sm1, Sm2,
10};
11use embassy_rp::pio_instr_util; 9use embassy_rp::pio_instr_util;
12use embassy_rp::relocate::RelocatedProgram; 10use embassy_rp::relocate::RelocatedProgram;
13use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
14 12
15fn setup_pio_task_sm0(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachineInstance<Pio0, Sm0>, pin: AnyPin) { 13fn setup_pio_task_sm0(pio: &mut PioCommon<PIO0>, sm: &mut PioStateMachineInstance<PIO0, 0>, pin: AnyPin) {
16 // Setup sm0 14 // Setup sm0
17 15
18 // Send data serially to pin 16 // Send data serially to pin
@@ -40,7 +38,7 @@ fn setup_pio_task_sm0(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachin
40} 38}
41 39
42#[embassy_executor::task] 40#[embassy_executor::task]
43async fn pio_task_sm0(mut sm: PioStateMachineInstance<Pio0, Sm0>) { 41async fn pio_task_sm0(mut sm: PioStateMachineInstance<'static, PIO0, 0>) {
44 sm.set_enable(true); 42 sm.set_enable(true);
45 43
46 let mut v = 0x0f0caffa; 44 let mut v = 0x0f0caffa;
@@ -51,7 +49,7 @@ async fn pio_task_sm0(mut sm: PioStateMachineInstance<Pio0, Sm0>) {
51 } 49 }
52} 50}
53 51
54fn setup_pio_task_sm1(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachineInstance<Pio0, Sm1>) { 52fn setup_pio_task_sm1(pio: &mut PioCommon<PIO0>, sm: &mut PioStateMachineInstance<PIO0, 1>) {
55 // Setupm sm1 53 // Setupm sm1
56 54
57 // Read 0b10101 repeatedly until ISR is full 55 // Read 0b10101 repeatedly until ISR is full
@@ -70,7 +68,7 @@ fn setup_pio_task_sm1(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachin
70} 68}
71 69
72#[embassy_executor::task] 70#[embassy_executor::task]
73async fn pio_task_sm1(mut sm: PioStateMachineInstance<Pio0, Sm1>) { 71async fn pio_task_sm1(mut sm: PioStateMachineInstance<'static, PIO0, 1>) {
74 sm.set_enable(true); 72 sm.set_enable(true);
75 loop { 73 loop {
76 let rx = sm.wait_pull().await; 74 let rx = sm.wait_pull().await;
@@ -78,7 +76,7 @@ async fn pio_task_sm1(mut sm: PioStateMachineInstance<Pio0, Sm1>) {
78 } 76 }
79} 77}
80 78
81fn setup_pio_task_sm2(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachineInstance<Pio0, Sm2>) { 79fn setup_pio_task_sm2(pio: &mut PioCommon<PIO0>, sm: &mut PioStateMachineInstance<PIO0, 2>) {
82 // Setup sm2 80 // Setup sm2
83 81
84 // Repeatedly trigger IRQ 3 82 // Repeatedly trigger IRQ 3
@@ -102,7 +100,7 @@ fn setup_pio_task_sm2(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachin
102} 100}
103 101
104#[embassy_executor::task] 102#[embassy_executor::task]
105async fn pio_task_sm2(mut sm: PioStateMachineInstance<Pio0, Sm2>) { 103async fn pio_task_sm2(mut sm: PioStateMachineInstance<'static, PIO0, 2>) {
106 sm.set_enable(true); 104 sm.set_enable(true);
107 loop { 105 loop {
108 sm.wait_irq(3).await; 106 sm.wait_irq(3).await;
@@ -115,11 +113,17 @@ async fn main(spawner: Spawner) {
115 let p = embassy_rp::init(Default::default()); 113 let p = embassy_rp::init(Default::default());
116 let pio = p.PIO0; 114 let pio = p.PIO0;
117 115
118 let (mut pio0, mut sm0, mut sm1, mut sm2, ..) = pio.split(); 116 let Pio {
119 117 mut common,
120 setup_pio_task_sm0(&mut pio0, &mut sm0, p.PIN_0.degrade()); 118 mut sm0,
121 setup_pio_task_sm1(&mut pio0, &mut sm1); 119 mut sm1,
122 setup_pio_task_sm2(&mut pio0, &mut sm2); 120 mut sm2,
121 ..
122 } = Pio::new(pio);
123
124 setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0.degrade());
125 setup_pio_task_sm1(&mut common, &mut sm1);
126 setup_pio_task_sm2(&mut common, &mut sm2);
123 spawner.spawn(pio_task_sm0(sm0)).unwrap(); 127 spawner.spawn(pio_task_sm0(sm0)).unwrap();
124 spawner.spawn(pio_task_sm1(sm1)).unwrap(); 128 spawner.spawn(pio_task_sm1(sm1)).unwrap();
125 spawner.spawn(pio_task_sm2(sm2)).unwrap(); 129 spawner.spawn(pio_task_sm2(sm2)).unwrap();
diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs
index 7d4919f75..0f1f6df12 100644
--- a/examples/rp/src/bin/pio_dma.rs
+++ b/examples/rp/src/bin/pio_dma.rs
@@ -4,7 +4,7 @@
4use defmt::info; 4use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_futures::join::join; 6use embassy_futures::join::join;
7use embassy_rp::pio::{PioCommon, PioPeripheral, PioStateMachine, ShiftDirection}; 7use embassy_rp::pio::{Pio, PioStateMachine, ShiftDirection};
8use embassy_rp::relocate::RelocatedProgram; 8use embassy_rp::relocate::RelocatedProgram;
9use embassy_rp::{pio_instr_util, Peripheral}; 9use embassy_rp::{pio_instr_util, Peripheral};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
@@ -19,7 +19,11 @@ fn swap_nibbles(v: u32) -> u32 {
19async fn main(_spawner: Spawner) { 19async fn main(_spawner: Spawner) {
20 let p = embassy_rp::init(Default::default()); 20 let p = embassy_rp::init(Default::default());
21 let pio = p.PIO0; 21 let pio = p.PIO0;
22 let (mut pio0, mut sm, ..) = pio.split(); 22 let Pio {
23 mut common,
24 sm0: mut sm,
25 ..
26 } = Pio::new(pio);
23 27
24 let prg = pio_proc::pio_asm!( 28 let prg = pio_proc::pio_asm!(
25 ".origin 0", 29 ".origin 0",
@@ -34,7 +38,7 @@ async fn main(_spawner: Spawner) {
34 ); 38 );
35 39
36 let relocated = RelocatedProgram::new(&prg.program); 40 let relocated = RelocatedProgram::new(&prg.program);
37 pio0.write_instr(relocated.origin() as usize, relocated.code()); 41 common.write_instr(relocated.origin() as usize, relocated.code());
38 pio_instr_util::exec_jmp(&mut sm, relocated.origin()); 42 pio_instr_util::exec_jmp(&mut sm, relocated.origin());
39 sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32); 43 sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32);
40 let pio::Wrap { source, target } = relocated.wrap(); 44 let pio::Wrap { source, target } = relocated.wrap();
diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs
new file mode 100644
index 000000000..59b4c1f52
--- /dev/null
+++ b/examples/rp/src/bin/pio_hd44780.rs
@@ -0,0 +1,243 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use core::fmt::Write;
6
7use embassy_executor::Spawner;
8use embassy_rp::dma::{AnyChannel, Channel};
9use embassy_rp::gpio::Pin;
10use embassy_rp::peripherals::PIO0;
11use embassy_rp::pio::{FifoJoin, Pio, PioStateMachine, PioStateMachineInstance, ShiftDirection};
12use embassy_rp::pwm::{Config, Pwm};
13use embassy_rp::relocate::RelocatedProgram;
14use embassy_rp::{into_ref, Peripheral, PeripheralRef};
15use embassy_time::{Duration, Instant, Timer};
16use {defmt_rtt as _, panic_probe as _};
17
18#[embassy_executor::main]
19async fn main(_spawner: Spawner) {
20 // this test assumes a 2x16 HD44780 display attached as follow:
21 // rs = PIN0
22 // rw = PIN1
23 // e = PIN2
24 // db4 = PIN3
25 // db5 = PIN4
26 // db6 = PIN5
27 // db7 = PIN6
28 // additionally a pwm signal for a bias voltage charge pump is provided on pin 15,
29 // allowing direct connection of the display to the RP2040 without level shifters.
30 let p = embassy_rp::init(Default::default());
31
32 let _pwm = Pwm::new_output_b(p.PWM_CH7, p.PIN_15, {
33 let mut c = Config::default();
34 c.divider = 125.into();
35 c.top = 100;
36 c.compare_b = 50;
37 c
38 });
39
40 let mut hd = HD44780::new(
41 p.PIO0, p.DMA_CH3, p.PIN_0, p.PIN_1, p.PIN_2, p.PIN_3, p.PIN_4, p.PIN_5, p.PIN_6,
42 )
43 .await;
44
45 loop {
46 struct Buf<const N: usize>([u8; N], usize);
47 impl<const N: usize> Write for Buf<N> {
48 fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
49 for b in s.as_bytes() {
50 if self.1 >= N {
51 return Err(core::fmt::Error);
52 }
53 self.0[self.1] = *b;
54 self.1 += 1;
55 }
56 Ok(())
57 }
58 }
59 let mut buf = Buf([0; 16], 0);
60 write!(buf, "up {}s", Instant::now().as_micros() as f32 / 1e6).unwrap();
61 hd.add_line(&buf.0[0..buf.1]).await;
62 Timer::after(Duration::from_secs(1)).await;
63 }
64}
65
66pub struct HD44780<'l> {
67 dma: PeripheralRef<'l, AnyChannel>,
68 sm: PioStateMachineInstance<'l, PIO0, 0>,
69
70 buf: [u8; 40],
71}
72
73impl<'l> HD44780<'l> {
74 pub async fn new(
75 pio: impl Peripheral<P = PIO0> + 'l,
76 dma: impl Peripheral<P = impl Channel> + 'l,
77 rs: impl Pin,
78 rw: impl Pin,
79 e: impl Pin,
80 db4: impl Pin,
81 db5: impl Pin,
82 db6: impl Pin,
83 db7: impl Pin,
84 ) -> HD44780<'l> {
85 into_ref!(dma);
86
87 let db7pin = db7.pin();
88 let Pio {
89 mut common, mut sm0, ..
90 } = Pio::new(pio);
91
92 // takes command words (<wait:24> <command:4> <0:4>)
93 let prg = pio_proc::pio_asm!(
94 r#"
95 .side_set 1 opt
96
97 loop:
98 out x, 24
99 delay:
100 jmp x--, delay
101 out pins, 4 side 1
102 out null, 4 side 0
103 jmp !osre, loop
104 irq 0
105 "#,
106 );
107
108 let rs = common.make_pio_pin(rs);
109 let rw = common.make_pio_pin(rw);
110 let e = common.make_pio_pin(e);
111 let db4 = common.make_pio_pin(db4);
112 let db5 = common.make_pio_pin(db5);
113 let db6 = common.make_pio_pin(db6);
114 let db7 = common.make_pio_pin(db7);
115
116 sm0.set_set_pins(&[&rs, &rw]);
117 embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b11);
118 sm0.set_set_pins(&[&e]);
119 embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b1);
120 sm0.set_set_pins(&[&db4, &db5, &db6, &db7]);
121 embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b11111);
122
123 let relocated = RelocatedProgram::new(&prg.program);
124 common.write_instr(relocated.origin() as usize, relocated.code());
125 embassy_rp::pio_instr_util::exec_jmp(&mut sm0, relocated.origin());
126 sm0.set_clkdiv(125 * 256);
127 let pio::Wrap { source, target } = relocated.wrap();
128 sm0.set_wrap(source, target);
129 sm0.set_side_enable(true);
130 sm0.set_out_pins(&[&db4, &db5, &db6, &db7]);
131 sm0.set_sideset_base_pin(&e);
132 sm0.set_sideset_count(2);
133 sm0.set_out_shift_dir(ShiftDirection::Left);
134 sm0.set_fifo_join(FifoJoin::TxOnly);
135 sm0.set_autopull(true);
136 sm0.set_pull_threshold(32);
137
138 sm0.set_enable(true);
139 // init to 8 bit thrice
140 sm0.push_tx((50000 << 8) | 0x30);
141 sm0.push_tx((5000 << 8) | 0x30);
142 sm0.push_tx((200 << 8) | 0x30);
143 // init 4 bit
144 sm0.push_tx((200 << 8) | 0x20);
145 // set font and lines
146 sm0.push_tx((50 << 8) | 0x20);
147 sm0.push_tx(0b1100_0000);
148
149 sm0.wait_irq(0).await;
150 sm0.set_enable(false);
151
152 // takes command sequences (<rs:1> <count:7>, data...)
153 // many side sets are only there to free up a delay bit!
154 let prg = pio_proc::pio_asm!(
155 r#"
156 .origin 7
157 .side_set 1
158
159 .wrap_target
160 pull side 0
161 out x 1 side 0 ; !rs
162 out y 7 side 0 ; #data - 1
163
164 ; rs/rw to e: >= 60ns
165 ; e high time: >= 500ns
166 ; e low time: >= 500ns
167 ; read data valid after e falling: ~5ns
168 ; write data hold after e falling: ~10ns
169
170 loop:
171 pull side 0
172 jmp !x data side 0
173 command:
174 set pins 0b00 side 0
175 jmp shift side 0
176 data:
177 set pins 0b01 side 0
178 shift:
179 out pins 4 side 1 [9]
180 nop side 0 [9]
181 out pins 4 side 1 [9]
182 mov osr null side 0 [7]
183 out pindirs 4 side 0
184 set pins 0b10 side 0
185 busy:
186 nop side 1 [9]
187 jmp pin more side 0 [9]
188 mov osr ~osr side 1 [9]
189 nop side 0 [4]
190 out pindirs 4 side 0
191 jmp y-- loop side 0
192 .wrap
193 more:
194 nop side 1 [9]
195 jmp busy side 0 [9]
196 "#
197 );
198
199 let relocated = RelocatedProgram::new(&prg.program);
200 common.write_instr(relocated.origin() as usize, relocated.code());
201 embassy_rp::pio_instr_util::exec_jmp(&mut sm0, relocated.origin());
202 let pio::Wrap { source, target } = relocated.wrap();
203 sm0.set_clkdiv(8 * 256); // ~64ns/insn
204 sm0.set_side_enable(false);
205 sm0.set_jmp_pin(db7pin);
206 sm0.set_wrap(source, target);
207 sm0.set_set_pins(&[&rs, &rw]);
208 sm0.set_out_pins(&[&db4, &db5, &db6, &db7]);
209 sm0.set_sideset_base_pin(&e);
210 sm0.set_sideset_count(1);
211 sm0.set_out_shift_dir(ShiftDirection::Left);
212 sm0.set_fifo_join(FifoJoin::TxOnly);
213
214 sm0.set_enable(true);
215
216 // display on and cursor on and blinking, reset display
217 sm0.dma_push(dma.reborrow(), &[0x81u8, 0x0f, 1]).await;
218
219 Self {
220 dma: dma.map_into(),
221 sm: sm0,
222 buf: [0x20; 40],
223 }
224 }
225
226 pub async fn add_line(&mut self, s: &[u8]) {
227 // move cursor to 0:0, prepare 16 characters
228 self.buf[..3].copy_from_slice(&[0x80, 0x80, 15]);
229 // move line 2 up
230 self.buf.copy_within(22..38, 3);
231 // move cursor to 1:0, prepare 16 characters
232 self.buf[19..22].copy_from_slice(&[0x80, 0xc0, 15]);
233 // file line 2 with spaces
234 self.buf[22..38].fill(0x20);
235 // copy input line
236 let len = s.len().min(16);
237 self.buf[22..22 + len].copy_from_slice(&s[0..len]);
238 // set cursor to 1:15
239 self.buf[38..].copy_from_slice(&[0x80, 0xcf]);
240
241 self.sm.dma_push(self.dma.reborrow(), &self.buf).await;
242 }
243}
diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs
index 041e8ae11..0975559d7 100644
--- a/examples/rp/src/bin/ws2812-pio.rs
+++ b/examples/rp/src/bin/ws2812-pio.rs
@@ -6,20 +6,19 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_rp::gpio::{self, Pin}; 7use embassy_rp::gpio::{self, Pin};
8use embassy_rp::pio::{ 8use embassy_rp::pio::{
9 FifoJoin, PioCommon, PioCommonInstance, PioInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance, 9 FifoJoin, Pio, PioCommon, PioInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection,
10 ShiftDirection, SmInstance,
11}; 10};
12use embassy_rp::pio_instr_util; 11use embassy_rp::pio_instr_util;
13use embassy_rp::relocate::RelocatedProgram; 12use embassy_rp::relocate::RelocatedProgram;
14use embassy_time::{Duration, Timer}; 13use embassy_time::{Duration, Timer};
15use smart_leds::RGB8; 14use smart_leds::RGB8;
16use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
17pub struct Ws2812<P: PioInstance, S: SmInstance> { 16pub struct Ws2812<'d, P: PioInstance, const S: usize> {
18 sm: PioStateMachineInstance<P, S>, 17 sm: PioStateMachineInstance<'d, P, S>,
19} 18}
20 19
21impl<P: PioInstance, S: SmInstance> Ws2812<P, S> { 20impl<'d, P: PioInstance, const S: usize> Ws2812<'d, P, S> {
22 pub fn new(mut pio: PioCommonInstance<P>, mut sm: PioStateMachineInstance<P, S>, pin: gpio::AnyPin) -> Self { 21 pub fn new(mut pio: PioCommon<'d, P>, mut sm: PioStateMachineInstance<'d, P, S>, pin: gpio::AnyPin) -> Self {
23 // Setup sm0 22 // Setup sm0
24 23
25 // prepare the PIO program 24 // prepare the PIO program
@@ -116,7 +115,7 @@ async fn main(_spawner: Spawner) {
116 info!("Start"); 115 info!("Start");
117 let p = embassy_rp::init(Default::default()); 116 let p = embassy_rp::init(Default::default());
118 117
119 let (pio0, sm0, _sm1, _sm2, _sm3) = p.PIO0.split(); 118 let Pio { common, sm0, .. } = Pio::new(p.PIO0);
120 119
121 // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit 120 // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit
122 // feather boards for the 2040 both have one built in. 121 // feather boards for the 2040 both have one built in.
@@ -125,7 +124,7 @@ async fn main(_spawner: Spawner) {
125 124
126 // For the thing plus, use pin 8 125 // For the thing plus, use pin 8
127 // For the feather, use pin 16 126 // For the feather, use pin 16
128 let mut ws2812 = Ws2812::new(pio0, sm0, p.PIN_8.degrade()); 127 let mut ws2812 = Ws2812::new(common, sm0, p.PIN_8.degrade());
129 128
130 // Loop forever making RGB values and pushing them out to the WS2812. 129 // Loop forever making RGB values and pushing them out to the WS2812.
131 loop { 130 loop {