#![no_std] #![no_main] #![feature(impl_trait_in_assoc_type)] use crate::usb::COBS_DOWNLINK; use molybdos::{ embassy_embedded_hal::shared_bus::asynch::spi::SpiDevice, embassy_executor, embassy_rp, embassy_rp::{ i2c::{ self, I2c, }, peripherals::{ I2C0, I2C1, PIO0, SPI0, SPI1, }, spi::{ self, Spi, }, }, embassy_sync::{ blocking_mutex::raw::{ CriticalSectionRawMutex, ThreadModeRawMutex, }, pipe::Pipe, pubsub, pubsub::PubSubBehavior, }, embedded_hal_async::spi::{ Operation, SpiDevice as _, }, embedded_sdmmc_async::{ VolumeIdx, VolumeManager, }, genlog, genlog::defmt, heapless, pal::StaticOutput, }; use ocularium::Downlink; mod bringup; mod usb; pub type BMESpi = Spi<'static, SPI1, spi::Async>; pub type BMESpiDev = SpiDevice<'static, CriticalSectionRawMutex, BMESpi, StaticOutput>; pub type SdSpi = Spi<'static, SPI0, spi::Async>; pub type SdSpiDev = SpiDevice<'static, CriticalSectionRawMutex, SdSpi, StaticOutput>; pub type SensorI2c = I2c<'static, I2C1, i2c::Async>; pub static I2S_PIPE: Pipe = Pipe::new(); #[::embassy_executor::main] async fn main(spawner: embassy_executor::Spawner) { molybdos::pal::heap::init(); defmt::info!("boot"); let bringup::Split { sd_spi, sd_cs, bme_spi, bme_cs, wdt, usb, i2s, i2s_dma, .. } = bringup::split(Default::default()); defmt::info!("split ok"); // spawner.must_spawn(molybdos::pal::watchdog(wdt)); let (acm,) = molybdos::lib::usb::bringup!( spawn, usb, molybdos::pal::UsbDriver, molybdos::lib::usb::config("npry", "ocularium", 0x8888, 0x0011), endpoints = { acm => |builder| molybdos::lib::usb::acm!(builder), } ); molybdos::lib::usb::start!(molybdos::pal::UsbDriver, acm, &usb::UPLINK, &usb::DOWNLINK); molybdos::lib::util::cobs::start!( ocularium::Uplink, &usb::UPLINK, &usb::COBS_UPLINK, ocularium::Downlink, &usb::DOWNLINK, &usb::COBS_DOWNLINK ); let mut spidev = SpiDevice::new(bme_spi, bme_cs); let data = &mut [0u8]; let result = spidev .transaction(&mut [Operation::Write(&[0x50 | (1 << 7)]), Operation::Read(data)]) .await; if let Err(e) = result { defmt::error!("reading spi dev: {}", defmt::Debug2Format(&e)); } else { defmt::info!("read chipid: {:x}", data[0]); } #[cfg(not(feature = "disable_sd"))] { let vm = molybdos::rt::sd::bringup!(sd_spi, SdSpi, sd_cs); { let vol = match VolumeManager::open_volume(vm, VolumeIdx(0)).await { Ok(x) => x, Err(e) => { defmt::error!("opening volume: {}", defmt::Debug2Format(&e)); loop { molybdos::embassy_time::Timer::after( molybdos::embassy_time::Duration::from_secs(1), ) .await; } }, }; } } spawner.must_spawn(drain_pipe()); spawner.must_spawn(run_i2s(i2s, i2s_dma)); loop { molybdos::embassy_time::Timer::after(molybdos::embassy_time::Duration::from_secs(1)).await; } } #[::embassy_executor::task] async fn run_i2s(mut i2s: bringup::StaticI2S, dma: embassy_rp::peripherals::DMA_CH5) { i2s.run::<960>(dma, &I2S_PIPE).await } #[::embassy_executor::task] async fn drain_pipe() { let publ = COBS_DOWNLINK.publisher().expect("getting publisher"); loop { let buf = &mut [0u8; 960]; let n = I2S_PIPE.read(buf).await; for elem in (&buf[..n]).chunks(48) { publ.publish_immediate(Downlink::PDM(heapless::Vec::from_slice(elem).unwrap())); } } }