Key components: - no_std core so it can be used bare metal on embedded systems - default implementation for RPi 2350, with midi input and I2s output using PIO - Visualiser for the web to play with on a dev system
67 lines
1.9 KiB
Rust
67 lines
1.9 KiB
Rust
//! 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<ThreadModeRawMutex, SynthParams> = Mutex::new(SynthParams::new());
|
|
|
|
// Register Embassy interrupt handlers for the peripherals we use.
|
|
bind_interrupts!(struct Irqs {
|
|
PIO0_IRQ_0 => PioIrqHandler<PIO0>;
|
|
UART0_IRQ => UartIrqHandler<UART0>;
|
|
DMA_IRQ_0 => dma::InterruptHandler<DMA_CH0>, dma::InterruptHandler<DMA_CH1>;
|
|
});
|
|
|
|
#[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());
|
|
}
|