#![no_main] #![no_std] use defmt_rtt as _; // global logger use panic_probe as _; use stm32f1xx_hal as _; // same panicking *behavior* as `panic-probe` but doesn't print a panic message // this prevents the panic message being printed *twice* when `defmt::panic` is invoked #[defmt::panic_handler] fn panic() -> ! { cortex_m::asm::udf() } use rtic::app; #[app(device = stm32f1xx_hal::pac, peripherals = true, dispatchers = [SPI2])] mod app { use stm32f1xx_hal::{ gpio::{gpioc, Output, PushPull}, prelude::*, usb::{Peripheral, UsbBus}, }; use usb_device::class_prelude::UsbBusAllocator; use usb_device::prelude::*; use usbd_audio::{AudioClass, AudioClassBuilder, Format, StreamConfig, TerminalType}; use systick_monotonic::Systick; #[monotonic(binds = SysTick, default = true)] type MonoTimer = Systick<1_000>; #[shared] struct Shared { usb_dev: UsbDevice<'static, UsbBus>, usb_audio: AudioClass<'static, UsbBus>, board_led: gpioc::PC13>, } #[local] struct Local {} #[init(local = [usb_bus: Option>> = None])] fn init(mut cx: init::Context) -> (Shared, Local, init::Monotonics) { let mut flash = cx.device.FLASH.constrain(); let rcc = cx.device.RCC.constrain(); // Freeze the configuration of all the clocks in the system and store the frozen frequencies in // `clocks` let clocks = rcc .cfgr .use_hse(8.MHz()) .sysclk(72.MHz()) .pclk1(36.MHz()) .freeze(&mut flash.acr); defmt::info!("Clock Setup done"); // Acquire the GPIOC peripheral let mut gpioa = cx.device.GPIOA.split(); //let mut gpiob = cx.device.GPIOB.split(); let mut gpioc = cx.device.GPIOC.split(); let board_led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh); defmt::info!("ADC Setup done"); // BluePill board has a pull-up resistor on the D+ line. // Pull the D+ pin down to send a RESET condition to the USB bus. // This forced reset is needed only for development, without it host // will not reset your device when you upload new firmware. let mut usb_dp = gpioa.pa12.into_push_pull_output(&mut gpioa.crh); let mut delay = cortex_m::delay::Delay::new(cx.core.SYST, clocks.sysclk().to_Hz()); usb_dp.set_low(); delay.delay_ms(10); cx.core.SYST = delay.free(); let usb_dm = gpioa.pa11; let usb_dp = usb_dp.into_floating_input(&mut gpioa.crh); let usb = Peripheral { usb: cx.device.USB, pin_dm: usb_dm, pin_dp: usb_dp, }; let usb_bus: &'static _ = cx.local.usb_bus.insert(UsbBus::new(usb)); let usb_audio = AudioClassBuilder::new() .input( StreamConfig::new_discrete(Format::S16le, 1, &[48000], TerminalType::InMicrophone) .unwrap(), ) .output( StreamConfig::new_discrete(Format::S16le, 1, &[48000], TerminalType::OutSpeaker) .unwrap(), ) .build(&usb_bus) .unwrap(); let usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd)) .max_packet_size_0(64) .manufacturer("Kiffie Labs") .product("Audio port") .serial_number("42") .build(); let mono = Systick::new(cx.core.SYST, clocks.sysclk().to_Hz()); ( Shared { usb_dev, usb_audio, board_led, }, Local {}, init::Monotonics(mono), ) } #[task(binds = USB_HP_CAN_TX, shared = [usb_dev, usb_audio])] fn usb_tx(cx: usb_tx::Context) { defmt::info!("usb_tx called"); let mut usb_dev = cx.shared.usb_dev; let mut usb_audio = cx.shared.usb_audio; (&mut usb_dev, &mut usb_audio).lock(|usb_dev, usb_audio| { if !usb_dev.poll(&mut [usb_audio]) { return; } }); } #[task(binds = USB_LP_CAN_RX0, shared = [usb_dev, usb_audio])] fn usb_rx0(cx: usb_rx0::Context) { defmt::info!("usb_rx called"); let mut usb_dev = cx.shared.usb_dev; let mut usb_audio = cx.shared.usb_audio; (&mut usb_dev, &mut usb_audio).lock(|usb_dev, usb_audio| { if !usb_dev.poll(&mut [usb_audio]) { return; } //TODO: Do something with usb_audio.read(); }); } #[idle(shared = [usb_audio, board_led])] fn idle(mut cx: idle::Context) -> ! { defmt::info!("Idle Task"); let sinetab = [ 0i16, 4276, 8480, 12539, 16383, 19947, 23169, 25995, 28377, 30272, 31650, 32486, 32767, 32486, 31650, 30272, 28377, 25995, 23169, 19947, 16383, 12539, 8480, 4276, 0, -4276, -8480, -12539, -16383, -19947, -23169, -25995, -28377, -30272, -31650, -32486, -32767, -32486, -31650, -30272, -28377, -25995, -23169, -19947, -16383, -12539, -8480, -4276, ]; let sinetab_le = unsafe { &*(&sinetab as *const _ as *const [u8; 96]) }; loop { defmt::info!("Writing samples"); cx.shared.usb_audio.lock(|usb_audio| { usb_audio.write(sinetab_le).ok(); }); rtic::export::wfi(); } } }