//! synth-embedded — RP2350 / Embassy audio engine entry point. //! //! Hardware assumed (adjust pin numbers in spawner calls to match your wiring): //! GPIO 9 → I2S BCK (bit clock) //! GPIO 10 → I2S LRCK (word select / left-right clock) //! GPIO 11 → I2S DATA //! GPIO 1 → UART0 RX (MIDI in, 31250 baud) //! //! Build: //! cargo build --release //! //! Flash (requires probe-rs and a debug probe): //! cargo run --release #![no_std] #![no_main] use defmt_rtt as _; use panic_probe as _; use embassy_executor::Spawner; use embassy_rp::{ bind_interrupts, dma, peripherals::{DMA_CH0, DMA_CH1, PIO0, UART0}, pio::InterruptHandler as PioIrqHandler, uart::InterruptHandler as UartIrqHandler, }; use embassy_sync::{blocking_mutex::raw::ThreadModeRawMutex, mutex::Mutex}; mod audio; mod midi; mod params; use params::SynthParams; /// Shared synthesiser state — written by the MIDI task, read by the audio task. /// /// `ThreadModeRawMutex` is appropriate here: both tasks run on core 0 and /// the mutex is never accessed from an interrupt handler. pub static PARAMS: Mutex = Mutex::new(SynthParams::new()); // Register Embassy interrupt handlers for the peripherals we use. bind_interrupts!(struct Irqs { PIO0_IRQ_0 => PioIrqHandler; UART0_IRQ => UartIrqHandler; DMA_IRQ_0 => dma::InterruptHandler, dma::InterruptHandler; }); #[embassy_executor::main] async fn main(spawner: Spawner) { let p = embassy_rp::init(Default::default()); defmt::info!("synth-embedded starting on RP2350"); // Audio output via PIO0 + DMA (I2S to PCM5102A or compatible DAC). spawner.spawn(audio::audio_task( p.PIO0, p.PIN_9, // BCK p.PIN_10, // LRCK p.PIN_11, // DATA p.DMA_CH0, ).unwrap()); // MIDI input via UART0 RX. spawner.spawn(midi::midi_task(p.UART0, p.PIN_1, p.DMA_CH1).unwrap()); }