Nenhuma descrição
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

i2s_master.rs 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. use crate::audio_buffer::{ReadBuffer, ReadPacket};
  2. use core::marker::PhantomData;
  3. use cortex_m::interrupt;
  4. use rp2040_hal::dma::{Channel, ChannelIndex, SingleBuffering, SingleBufferingConfig};
  5. use rp2040_hal::gpio::bank0::{Gpio0, Gpio1, Gpio3, Gpio6};
  6. use rp2040_hal::gpio::{Function, Pin, Pio0};
  7. use rp2040_hal::pac::PIO0;
  8. use rp2040_hal::pio::{
  9. PIOBuilder, PIOExt, StateMachineIndex, Tx, UninitStateMachine, ValidStateMachine, PIO,
  10. };
  11. pub trait PinConfig {
  12. type PIO;
  13. const OUT_MASK: u32;
  14. }
  15. impl PinConfig
  16. for (
  17. Pin<Gpio0, Function<Pio0>>,
  18. Pin<Gpio1, Function<Pio0>>,
  19. Pin<Gpio6, Function<Pio0>>,
  20. Pin<Gpio3, Function<Pio0>>,
  21. )
  22. {
  23. type PIO = PIO0;
  24. const OUT_MASK: u32 = 0x4b;
  25. }
  26. pub struct I2sMaster<SM: ValidStateMachine, DMACH: ChannelIndex, LRCLK, BCLK, SDO, SDI> {
  27. tx: Option<SingleBuffering<Channel<DMACH>, ReadPacket<4>, Tx<SM>>>,
  28. out_buffer: ReadBuffer<4>,
  29. _phantom: PhantomData<(SM, LRCLK, BCLK, SDO, SDI)>,
  30. }
  31. impl<P: PIOExt, SM: StateMachineIndex, DMACH: ChannelIndex, LRCLK, BCLK, SDO, SDI>
  32. I2sMaster<(P, SM), DMACH, LRCLK, BCLK, SDO, SDI>
  33. where
  34. (LRCLK, BCLK, SDO, SDI): PinConfig,
  35. {
  36. pub fn init(
  37. pio: &mut PIO<P>,
  38. sm: UninitStateMachine<(P, SM)>,
  39. dma: Channel<DMACH>,
  40. out_buffer: ReadBuffer<4>,
  41. _lrclk: LRCLK,
  42. _bclk: BCLK,
  43. _sdo: SDO,
  44. _sdi: SDI,
  45. ) -> Self {
  46. let program = pio_proc::pio!(
  47. 32,
  48. "
  49. .side_set 2
  50. .wrap_target
  51. pull noblock side 0b11 [0]
  52. set x, 14 side 0b11 [0]
  53. leftloop:
  54. out pins, 1 side 0b00 [6]
  55. in pins, 1 side 0b01 [5]
  56. jmp x-- leftloop side 0b01 [0]
  57. out pins, 1 side 0b00 [6]
  58. in pins, 1 side 0b01 [5]
  59. set x, 14 side 0b01 [0]
  60. rightloop:
  61. out pins, 1 side 0b10 [6]
  62. in pins, 1 side 0b11 [5]
  63. jmp x-- rightloop side 0b11 [0]
  64. out pins, 1 side 0b10 [6]
  65. in pins, 1 side 0b11 [3]
  66. push noblock side 0b11 [0]
  67. .wrap
  68. "
  69. );
  70. let installed = pio.install(&program.program).unwrap();
  71. let (mut sm, _rx, tx) = PIOBuilder::from_program(installed)
  72. .side_set_pin_base(0)
  73. //.set_pins(6, 1)
  74. .out_pins(6, 1)
  75. .in_pin_base(3)
  76. .clock_divisor(4.0)
  77. .build(sm);
  78. sm.set_pindirs_with_mask(
  79. <(LRCLK, BCLK, SDO, SDI)>::OUT_MASK,
  80. <(LRCLK, BCLK, SDO, SDI)>::OUT_MASK,
  81. );
  82. // Start the first DMA transfer.
  83. let packet = interrupt::free(|cs| out_buffer.borrow_read(cs).unwrap());
  84. let tx = SingleBufferingConfig::new(dma, packet, tx).start();
  85. // Start I2S.
  86. // TODO: Synchronized start of multiple I2S instances?
  87. sm.start();
  88. I2sMaster {
  89. tx: Some(tx),
  90. out_buffer,
  91. _phantom: PhantomData,
  92. }
  93. }
  94. pub fn next_packet(&mut self) {
  95. if !self.tx.as_mut().unwrap().check_irq0() {
  96. return;
  97. }
  98. let (dma, prev_packet, tx) = self.tx.take().unwrap().wait();
  99. let packet = interrupt::free(|cs| {
  100. self.out_buffer.read_finished(prev_packet, cs);
  101. self.out_buffer.borrow_read(cs).unwrap()
  102. });
  103. self.tx = Some(SingleBufferingConfig::new(dma, packet, tx).start());
  104. }
  105. }