Geen omschrijving
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

main.rs 9.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. #![no_std]
  2. #![no_main]
  3. //use panic_halt as _;
  4. use cortex_m::interrupt::CriticalSection;
  5. use panic_semihosting as _;
  6. use rp2040_hal::pac::UART0;
  7. use rp2040_hal::uart;
  8. mod audio_buffer;
  9. mod i2s_master;
  10. mod usb;
  11. mod usb_audio;
  12. #[link_section = ".boot2"]
  13. #[used]
  14. pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
  15. /*pub fn uart<'cs>(cs: &'cs CriticalSection) -> &'cs mut uart::UartPeripheral<uart::Enabled, UART0> {
  16. use panic_write::PanicHandler;
  17. unsafe {
  18. let panic_handler = app::PANIC_HANDLER.borrow(cs).get();
  19. let panic_handler_ref = core::mem::transmute::<
  20. *mut Option<core::pin::Pin<PanicHandler<uart::UartPeripheral<uart::Enabled, UART0>>>>,
  21. &mut Option<core::pin::Pin<PanicHandler<uart::UartPeripheral<uart::Enabled, UART0>>>>,
  22. >(panic_handler);
  23. panic_handler_ref.as_mut().unwrap()
  24. }
  25. }*/
  26. #[rtic::app(device = rp2040_hal::pac, peripherals = true, dispatchers = [RTC_IRQ, XIP_IRQ])]
  27. mod app {
  28. use embedded_hal::digital::v2::OutputPin;
  29. use embedded_time::duration::Milliseconds;
  30. use embedded_time::rate::{Extensions, Megahertz};
  31. use rp2040_hal::clocks::ClocksManager;
  32. use rp2040_hal::gpio;
  33. //use rp2040_hal::pio::{PIOBuilder, PIOExt};
  34. use crate::audio_buffer::AudioBuffer;
  35. use crate::i2s_master::I2sMaster;
  36. use crate::usb::Usb;
  37. //use core::cell::UnsafeCell;
  38. use core::fmt::Write;
  39. use cortex_m::interrupt::{self, Mutex};
  40. //use panic_write::PanicHandler;
  41. use rp2040_hal::dma::{DMAExt, SingleChannel, CH0};
  42. use rp2040_hal::gpio::bank0::{Gpio0, Gpio1, Gpio3, Gpio6};
  43. use rp2040_hal::gpio::{Function, FunctionUart, Pin, Pio0};
  44. use rp2040_hal::pac::UART0;
  45. use rp2040_hal::pio::{PIOExt, PIO0SM0};
  46. use rp2040_hal::pll::common_configs::PLL_USB_48MHZ;
  47. use rp2040_hal::pll::{setup_pll_blocking, PLLConfig};
  48. use rp2040_hal::sio::Sio;
  49. use rp2040_hal::timer::Timer;
  50. //use rp2040_hal::uart;
  51. use rp2040_hal::usb::UsbBus;
  52. use rp2040_hal::watchdog::Watchdog;
  53. use rp2040_hal::xosc::setup_xosc_blocking;
  54. use systick_monotonic::Systick;
  55. use usb_device::class_prelude::*;
  56. const XOSC_CRYSTAL_FREQ: u32 = 12_000_000;
  57. pub const PLL_SYS_86MHZ: PLLConfig<Megahertz> = PLLConfig {
  58. vco_freq: Megahertz(1032),
  59. refdiv: 1,
  60. post_div1: 6,
  61. post_div2: 2,
  62. };
  63. static AUDIO_BUFFER: AudioBuffer<4> = AudioBuffer::new();
  64. /*pub static UART: Mutex<
  65. MaybeUninit<Option<&'static mut uart::UartPeripheral<uart::Enabled, UART0>>>,
  66. > = Mutex::new(UnsafeCell::new(None));*/
  67. /*pub static mut PANIC_HANDLER: Mutex<
  68. UnsafeCell<
  69. Option<core::pin::Pin<PanicHandler<uart::UartPeripheral<uart::Enabled, UART0>>>>,
  70. >,
  71. > = Mutex::new(UnsafeCell::new(None));*/
  72. #[monotonic(binds = SysTick, default = true)]
  73. type SystickMono = Systick<100>;
  74. #[shared]
  75. struct Shared {}
  76. #[local]
  77. struct Local {
  78. led: gpio::Pin<gpio::pin::bank0::Gpio25, gpio::PushPullOutput>,
  79. i2s: I2sMaster<
  80. PIO0SM0,
  81. CH0,
  82. Pin<Gpio0, Function<Pio0>>,
  83. Pin<Gpio1, Function<Pio0>>,
  84. Pin<Gpio6, Function<Pio0>>,
  85. Pin<Gpio3, Function<Pio0>>,
  86. >,
  87. usb: Usb,
  88. }
  89. #[init]
  90. fn init(c: init::Context) -> (Shared, Local, init::Monotonics) {
  91. let mut resets = c.device.RESETS;
  92. // The timer needs a 1MHz input from the watchdog.
  93. let mut watchdog = Watchdog::new(c.device.WATCHDOG);
  94. watchdog.enable_tick_generation((XOSC_CRYSTAL_FREQ / 1000000) as u8);
  95. // We let an LED blink to show that the system is still alive.
  96. let sio = Sio::new(c.device.SIO);
  97. let pins = gpio::Pins::new(
  98. c.device.IO_BANK0,
  99. c.device.PADS_BANK0,
  100. sio.gpio_bank0,
  101. &mut resets,
  102. );
  103. // We select a 86 MHz system clock as that lets us generate a clean and precise 12.288 MHz
  104. // master clock by dividing the system clock by 7.
  105. // TODO: Select 123 MHz instead (0.1% deviation, whereas 86 MHz results in 0.02%
  106. // deviation), or look for an even better frequency that is not a multiple of 1MHz.
  107. let mut clocks = ClocksManager::new(c.device.CLOCKS);
  108. let xosc = setup_xosc_blocking(c.device.XOSC, XOSC_CRYSTAL_FREQ.Hz())
  109. .ok()
  110. .unwrap();
  111. let pll_sys = setup_pll_blocking(
  112. c.device.PLL_SYS,
  113. xosc.operating_frequency().into(),
  114. PLL_SYS_86MHZ,
  115. &mut clocks,
  116. &mut resets,
  117. )
  118. .ok()
  119. .unwrap();
  120. let pll_usb = setup_pll_blocking(
  121. c.device.PLL_USB,
  122. xosc.operating_frequency().into(),
  123. PLL_USB_48MHZ,
  124. &mut clocks,
  125. &mut resets,
  126. )
  127. .ok()
  128. .unwrap();
  129. let _clocks = clocks.init_default(&xosc, &pll_sys, &pll_usb).ok().unwrap();
  130. let mut led = pins.gpio25.into_push_pull_output();
  131. led.set_low().ok().unwrap();
  132. /*// We need a UART to debug panics.
  133. let mut uart = uart::UartPeripheral::<_, _>::enable(
  134. c.device.UART0,
  135. &mut resets,
  136. uart::common_configs::_115200_8_N_1,
  137. clocks.peripheral_clock.into(),
  138. )
  139. .unwrap();
  140. let _tx_pin = pins.gpio16.into_mode::<FunctionUart>();
  141. let _rx_pin = pins.gpio17.into_mode::<FunctionUart>();
  142. writeln!(&mut uart, "Initializing...\r").unwrap();
  143. interrupt::free(|cs| unsafe {
  144. let panic_handler = PANIC_HANDLER.borrow(cs);
  145. *panic_handler.get() = Some(PanicHandler::new(uart));
  146. writeln!(super::uart(cs), "Panic handler installed.\r").unwrap();
  147. });*/
  148. // We need a timer so that we can determine the USB SOF frequency for asynchronous USB
  149. // audio.
  150. let timer = Timer::new(c.device.TIMER, &mut resets);
  151. // We initialize the output audio buffers with some data. As the I2S input buffers are
  152. // filled at the same rate as the I2S output buffers, this initial state ensures that the
  153. // output buffers never run empty (note that the USB audio interface performs its own
  154. // adaptive synchronization).
  155. interrupt::free(|cs| {
  156. let write = AUDIO_BUFFER.write();
  157. for _ in 0..2 {
  158. let mut packet = write.borrow_write(cs).unwrap();
  159. let data = packet.as_mut();
  160. for i in 0..data.len() {
  161. //data[i] = 0x80000000; // "0"
  162. data[i] = 0xa5a5aa55;
  163. }
  164. write.write_finished(packet, cs);
  165. }
  166. });
  167. // Configure USB audio.
  168. static mut USB_BUS: Option<UsbBusAllocator<UsbBus>> = None;
  169. unsafe {
  170. USB_BUS = Some(UsbBusAllocator::new(UsbBus::new(
  171. c.device.USBCTRL_REGS,
  172. c.device.USBCTRL_DPRAM,
  173. clocks.usb_clock,
  174. true,
  175. &mut resets,
  176. )))
  177. };
  178. let usb = Usb::init(
  179. unsafe { USB_BUS.as_ref().unwrap() },
  180. AUDIO_BUFFER.write(),
  181. timer,
  182. );
  183. // Configure the PIO unit and start I2S.
  184. let mut dma = c.device.DMA.split(&mut resets);
  185. let (mut pio, sm0, _sm1, _sm2, _sm3) = c.device.PIO0.split(&mut resets);
  186. dma.ch0.listen_irq0();
  187. let i2s = I2sMaster::init(
  188. &mut pio,
  189. sm0,
  190. dma.ch0,
  191. AUDIO_BUFFER.read(),
  192. pins.gpio0.into_mode(),
  193. pins.gpio1.into_mode(),
  194. pins.gpio6.into_mode(),
  195. pins.gpio3.into_mode(),
  196. );
  197. // A speaker amplifier (TAS5760) is connected to I2S - we need to configure it via I2C.
  198. // TODO
  199. // TODO: I2C stuff should happen in a low-priority task as we do not want to make data
  200. // streaming to I2S wait.
  201. let systick = c.core.SYST;
  202. let mono = Systick::new(systick, 86_000_000);
  203. blink::spawn().ok().unwrap();
  204. (Shared {}, Local { led, i2s, usb }, init::Monotonics(mono))
  205. }
  206. #[task(shared = [], local = [led, state: bool = false])]
  207. fn blink(ctx: blink::Context) {
  208. blink::spawn_after(Milliseconds(500_u32)).ok().unwrap();
  209. *ctx.local.state = !*ctx.local.state;
  210. if *ctx.local.state {
  211. ctx.local.led.set_high().ok().unwrap();
  212. } else {
  213. ctx.local.led.set_low().ok().unwrap();
  214. }
  215. }
  216. /*/// DMA interrupt handler.
  217. ///
  218. /// DMA interrupts need to have highest priority as we need to quickly restart the DMA transfer
  219. /// to ensure that the PIO FIFO always contains data.
  220. #[task(binds = DMA_IRQ_0, priority = 3, local = [i2s])]
  221. fn dma(ctx: dma::Context) {
  222. ctx.local.i2s.next_packet();
  223. process_buffers::spawn().unwrap();
  224. }
  225. #[task]
  226. fn process_buffers(_: process_buffers::Context) {
  227. interrupt::free(|cs| {
  228. // If we have run out of data from USB, insert a packet filled with zeros.
  229. // TODO
  230. let write = AUDIO_BUFFER.write();
  231. let mut packet = write.borrow_write(cs).unwrap();
  232. let data = packet.as_mut();
  233. for i in 0..data.len() {
  234. //data[i] = 0x80000000; // "0"
  235. data[i] = 0xa5a5aa55;
  236. }
  237. write.write_finished(packet, cs);
  238. });
  239. }*/
  240. /// USB interrupt handler.
  241. ///
  242. /// USB interrupts have a high priority (albeit not as high as DMA) so that we can precisely
  243. /// measure the SOF frequency relative to our system clock. The frequency ratio is required for
  244. /// asynchronous USB audio.
  245. #[task(binds = USBCTRL_IRQ, priority = 2, local = [usb])]
  246. fn usb(ctx: usb::Context) {
  247. ctx.local.usb.poll();
  248. }
  249. }