Нет описания
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

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