diff --git a/Cargo.toml b/Cargo.toml index 2e4371a..1b5e86f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,3 +54,6 @@ codegen-units = 1 # better optimizations debug = true # symbols are nice and they don't increase the size in flash lto = true # better optimizations opt-level = "s" # optimize for binary size + +[dev-dependencies] +embedded-midi = "0.1.0" diff --git a/examples/midi.rs b/examples/midi.rs new file mode 100644 index 0000000..3d8a234 --- /dev/null +++ b/examples/midi.rs @@ -0,0 +1,152 @@ +//! examples/midi.rs +#![no_main] +#![no_std] +use log::info; + +use embedded_midi::{MidiMessage, MidiOut}; + +use libdaisy::{gpio, prelude::*, system::System}; +use stm32h7xx_hal::{ + stm32, + timer::{Event, Timer}, +}; + +#[derive(Copy, Clone)] +enum NoteState { + On, + Off, + Idle, +} + +impl NoteState { + pub fn next(&self) -> Self { + match self { + Self::On => Self::Off, + Self::Off => Self::Idle, + Self::Idle => Self::On, + } + } +} + +#[rtic::app( + device = stm32h7xx_hal::stm32, + peripherals = true, + monotonic = rtic::cyccnt::CYCCNT, +)] +const APP: () = { + struct Resources { + seed_led: gpio::SeedLed, + timer2: Timer, + midi_out: MidiOut>, + } + + #[init] + fn init(ctx: init::Context) -> init::LateResources { + libdaisy::logger::init(); + + let device = ctx.device; + let mut ccdr = System::init_clocks(device.PWR, device.RCC, &device.SYSCFG); + let mut timer2 = device + .TIM2 + .timer(100.ms(), ccdr.peripheral.TIM2, &mut ccdr.clocks); + timer2.listen(Event::TimeOut); + + info!("Startup done!"); + + timer2.set_freq(100.ms()); + + let gpioa = device.GPIOA.split(ccdr.peripheral.GPIOA); + let gpiob = device.GPIOB.split(ccdr.peripheral.GPIOB); + let gpioc = device.GPIOC.split(ccdr.peripheral.GPIOC); + let gpiod = device.GPIOD.split(ccdr.peripheral.GPIOD); + let gpiog = device.GPIOG.split(ccdr.peripheral.GPIOG); + + let mut gpio = crate::gpio::GPIO::init( + gpioc.pc7, + gpiob.pb11, + Some(gpiob.pb12), + Some(gpioc.pc11), + Some(gpioc.pc10), + Some(gpioc.pc9), + Some(gpioc.pc8), + Some(gpiod.pd2), + Some(gpioc.pc12), + Some(gpiog.pg10), + Some(gpiog.pg11), + Some(gpiob.pb4), + Some(gpiob.pb5), + Some(gpiob.pb8), + Some(gpiob.pb9), + Some(gpiob.pb6), + Some(gpiob.pb7), + Some(gpioc.pc0), + Some(gpioa.pa3), + Some(gpiob.pb1), + Some(gpioa.pa7), + Some(gpioa.pa6), + Some(gpioc.pc1), + Some(gpioc.pc4), + Some(gpioa.pa5), + Some(gpioa.pa4), + Some(gpioa.pa1), + Some(gpioa.pa0), + Some(gpiod.pd11), + Some(gpiog.pg9), + Some(gpioa.pa2), + Some(gpiob.pb14), + Some(gpiob.pb15), + ); + + let (serial_tx, _) = libdaisy::serial::midi( + gpio.daisy13.take().unwrap(), + gpio.daisy14.take().unwrap(), + device.USART1, + ccdr.peripheral.USART1, + &ccdr.clocks, + ) + .unwrap() + .split(); + + init::LateResources { + seed_led: gpio.led, + timer2, + midi_out: MidiOut::new(serial_tx), + } + } + + #[task(binds = TIM2, resources = [timer2, seed_led, midi_out] )] + fn send(ctx: send::Context) { + static mut NOTE: NoteState = NoteState::Idle; + static mut NOTE_NUM: u8 = 0; + + ctx.resources.timer2.clear_irq(); + + *NOTE = NOTE.next(); + + let note = *NOTE_NUM; + + match NOTE { + NoteState::On => { + ctx.resources.seed_led.set_high().unwrap(); + ctx.resources + .midi_out + .write(&MidiMessage::NoteOn(0u8.into(), note.into(), 0x40u8.into())) + .unwrap(); + } + NoteState::Off => { + ctx.resources.seed_led.set_low().unwrap(); + ctx.resources + .midi_out + .write(&MidiMessage::NoteOff( + 0u8.into(), + note.into(), + 0x40u8.into(), + )) + .unwrap(); + } + NoteState::Idle => { + *NOTE_NUM = (note + 1) & 0x7F; + } + }; + } +}; diff --git a/src/lib.rs b/src/lib.rs index 0336d68..2c061f3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,6 +26,7 @@ pub mod logger; pub mod mpu; pub mod prelude; pub mod sdram; +pub mod serial; pub mod system; // Delay for ms, note if interrupts are active delay time will extend diff --git a/src/serial.rs b/src/serial.rs new file mode 100644 index 0000000..88919ff --- /dev/null +++ b/src/serial.rs @@ -0,0 +1,26 @@ +use stm32h7xx_hal::{ + gpio::Analog, + prelude::*, + rcc, + serial::{config::InvalidConfig, Serial, SerialExt}, + stm32::USART1, +}; + +/// Get a configured serial MIDI device +pub fn midi( + daisy13: crate::gpio::Daisy13, + daisy14: crate::gpio::Daisy14, + usart1_d: USART1, + usart1_p: rcc::rec::Usart1, + clocks: &rcc::CoreClocks, +) -> Result, InvalidConfig> { + let (tx, rx) = (daisy13.into_alternate_af7(), daisy14.into_alternate_af7()); + usart1_d.serial( + (tx, rx), + stm32h7xx_hal::serial::config::Config::default() + .baudrate(31_250.bps()) + .parity_none(), + usart1_p, + &clocks, + ) +}