//! This example shows powerful PIO module in the RP2040 chip. #![no_std] #![no_main] #![feature(type_alias_impl_trait)] use defmt::info; use embassy_executor::Spawner; use embassy_futures::join::join; use embassy_rp::peripherals::PIO0; use embassy_rp::pio::{Config, InterruptHandler, Pio, ShiftConfig, ShiftDirection}; use embassy_rp::relocate::RelocatedProgram; use embassy_rp::{bind_interrupts, Peripheral}; use fixed::traits::ToFixed; use fixed_macro::types::U56F8; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { PIO0_IRQ_0 => InterruptHandler; }); fn swap_nibbles(v: u32) -> u32 { let v = (v & 0x0f0f_0f0f) << 4 | (v & 0xf0f0_f0f0) >> 4; let v = (v & 0x00ff_00ff) << 8 | (v & 0xff00_ff00) >> 8; (v & 0x0000_ffff) << 16 | (v & 0xffff_0000) >> 16 } #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); let pio = p.PIO0; let Pio { mut common, sm0: mut sm, .. } = Pio::new(pio, Irqs); let prg = pio_proc::pio_asm!( ".origin 0", "set pindirs,1", ".wrap_target", "set y,7", "loop:", "out x,4", "in x,4", "jmp y--, loop", ".wrap", ); let relocated = RelocatedProgram::new(&prg.program); let mut cfg = Config::default(); cfg.use_program(&common.load_program(&relocated), &[]); cfg.clock_divider = (U56F8!(125_000_000) / U56F8!(10_000)).to_fixed(); cfg.shift_in = ShiftConfig { auto_fill: true, threshold: 32, direction: ShiftDirection::Left, }; cfg.shift_out = ShiftConfig { auto_fill: true, threshold: 32, direction: ShiftDirection::Right, }; sm.set_config(&cfg); sm.set_enable(true); let mut dma_out_ref = p.DMA_CH0.into_ref(); let mut dma_in_ref = p.DMA_CH1.into_ref(); let mut dout = [0x12345678u32; 29]; for i in 1..dout.len() { dout[i] = (dout[i - 1] & 0x0fff_ffff) * 13 + 7; } let mut din = [0u32; 29]; loop { let (rx, tx) = sm.rx_tx(); join( tx.dma_push(dma_out_ref.reborrow(), &dout), rx.dma_pull(dma_in_ref.reborrow(), &mut din), ) .await; for i in 0..din.len() { assert_eq!(din[i], swap_nibbles(dout[i])); } info!("Swapped {} words", dout.len()); } }