stm32-usbd-audio-example/src/main.rs

170 lines
5.4 KiB
Rust

#![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<Peripheral>>,
usb_audio: AudioClass<'static, UsbBus<Peripheral>>,
board_led: gpioc::PC13<Output<PushPull>>,
}
#[local]
struct Local {}
#[init(local = [usb_bus: Option<UsbBusAllocator<UsbBus<Peripheral>>> = 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();
}
}
}