浏览代码

WIP: Initial USB audio class implementation.

当前提交
b8078b5736
共有 13 个文件被更改,包括 2309 次插入0 次删除
  1. 14
    0
      .cargo/config
  2. 2
    0
      .gitignore
  3. 998
    0
      Cargo.lock
  4. 36
    0
      Cargo.toml
  5. 31
    0
      build.rs
  6. 13
    0
      memory.x
  7. 6
    0
      openocd.cfg
  8. 26
    0
      openocd.gdb
  9. 205
    0
      src/audio_buffer.rs
  10. 121
    0
      src/i2s_master.rs
  11. 278
    0
      src/main.rs
  12. 66
    0
      src/usb.rs
  13. 513
    0
      src/usb_audio.rs

+ 14
- 0
.cargo/config 查看文件

@@ -0,0 +1,14 @@
1
+[build]
2
+# Instruction set of Cortex-M0+
3
+target = "thumbv6m-none-eabi"
4
+
5
+[target.'cfg(all(target_arch = "arm", target_os = "none"))']
6
+rustflags = [
7
+    "-C", "link-arg=--nmagic",
8
+    "-C", "link-arg=-Tlink.x",
9
+    "-C", "inline-threshold=5",
10
+    "-C", "no-vectorize-loops",
11
+]
12
+#runner = "elf2uf2-rs -d"
13
+runner = "arm-none-eabi-gdb -x openocd.gdb"
14
+

+ 2
- 0
.gitignore 查看文件

@@ -0,0 +1,2 @@
1
+/target
2
+*.swp

+ 998
- 0
Cargo.lock
文件差异内容过多而无法显示
查看文件


+ 36
- 0
Cargo.toml 查看文件

@@ -0,0 +1,36 @@
1
+[package]
2
+name = "rp2040-usb-sound-card"
3
+version = "0.1.0"
4
+edition = "2018"
5
+resolver = "2"
6
+
7
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8
+
9
+[dependencies]
10
+cortex-m = "0.7.2"
11
+cortex-m-rt = "0.7"
12
+cortex-m-rtic = "0.6.0-alpha.5"
13
+cortex-m-semihosting = "0.3.7"
14
+embedded-hal ="0.2.5"
15
+embedded-time = "0.12.0"
16
+nb = "1.0"
17
+#panic-halt = "0.2.0"
18
+panic-semihosting = "0.5"
19
+#panic-write = "0.1.0"
20
+pio = { git = "https://github.com/rp-rs/pio-rs.git", branch = "main" }
21
+pio-proc = { git = "https://github.com/rp-rs/pio-rs.git", branch = "main" }
22
+#rp2040-hal = { git = "https://github.com/rp-rs/rp-hal.git", features = ["rt"] }
23
+rp2040-hal = { path = "../rp-hal/rp2040-hal", features = ["rt"] }
24
+rp2040-boot2 = "0.1.2"
25
+stable_deref_trait = { version = "1.2.0", default-features = false }
26
+systick-monotonic = "0.1.0-alpha.0"
27
+usb-device = { version = "0.2.8", features = ["control-buffer-256"] }
28
+void = { version = "*", default_features = false }
29
+
30
+[patch.crates-io]
31
+usb-device = { path = "../usb-device" }
32
+
33
+[profile]
34
+[profile.release]
35
+debug = true
36
+lto = true

+ 31
- 0
build.rs 查看文件

@@ -0,0 +1,31 @@
1
+//! This build script copies the `memory.x` file from the crate root into
2
+//! a directory where the linker can always find it at build time.
3
+//! For many projects this is optional, as the linker always searches the
4
+//! project root directory -- wherever `Cargo.toml` is. However, if you
5
+//! are using a workspace or have a more complicated build setup, this
6
+//! build script becomes required. Additionally, by requesting that
7
+//! Cargo re-run the build script whenever `memory.x` is changed,
8
+//! updating `memory.x` ensures a rebuild of the application with the
9
+//! new memory settings.
10
+
11
+use std::env;
12
+use std::fs::File;
13
+use std::io::Write;
14
+use std::path::PathBuf;
15
+
16
+fn main() {
17
+    // Put `memory.x` in our output directory and ensure it's
18
+    // on the linker search path.
19
+    let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
20
+    File::create(out.join("memory.x"))
21
+        .unwrap()
22
+        .write_all(include_bytes!("memory.x"))
23
+        .unwrap();
24
+    println!("cargo:rustc-link-search={}", out.display());
25
+
26
+    // By default, Cargo will re-run a build script whenever
27
+    // any file in the project changes. By specifying `memory.x`
28
+    // here, we ensure the build script is only re-run when
29
+    // `memory.x` is changed.
30
+    println!("cargo:rerun-if-changed=memory.x");
31
+}

+ 13
- 0
memory.x 查看文件

@@ -0,0 +1,13 @@
1
+MEMORY {
2
+    BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100
3
+    FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100
4
+    RAM   : ORIGIN = 0x20000000, LENGTH = 256K
5
+}
6
+
7
+SECTIONS {
8
+    /* ### Boot loader */
9
+    .boot2 ORIGIN(BOOT2) :
10
+    {
11
+        KEEP(*(.boot2));
12
+    } > BOOT2
13
+} INSERT BEFORE .text;

+ 6
- 0
openocd.cfg 查看文件

@@ -0,0 +1,6 @@
1
+source [find interface/cmsis-dap.cfg]
2
+transport select swd
3
+
4
+adapter speed 100
5
+source [find target/rp2040.cfg]
6
+

+ 26
- 0
openocd.gdb 查看文件

@@ -0,0 +1,26 @@
1
+set history save on
2
+set confirm off
3
+target extended-remote :3333
4
+monitor arm semihosting enable
5
+monitor reset halt
6
+
7
+# print demangled symbols
8
+set print asm-demangle on
9
+
10
+# set backtrace limit to not have infinite backtrace loops
11
+set backtrace limit 32
12
+
13
+# detect unhandled exceptions, hard faults and panics
14
+break DefaultHandler
15
+break HardFault
16
+#break rust_begin_unwind
17
+
18
+#break main
19
+
20
+load
21
+run
22
+# continue
23
+# monitor verify
24
+# monitor reset
25
+# quit
26
+

+ 205
- 0
src/audio_buffer.rs 查看文件

@@ -0,0 +1,205 @@
1
+//! Audio buffer type to transfer audio data within different software/hardware components.
2
+#![warn(missing_docs)]
3
+
4
+use core::cell::{Cell, UnsafeCell};
5
+use core::ops::Deref;
6
+
7
+use cortex_m::interrupt::{CriticalSection, Mutex};
8
+use stable_deref_trait::StableDeref;
9
+
10
+/// Each packet contains 1 millisecond of audio data (48 samples at 48000kHz).
11
+///
12
+/// This translates two twice the number of values, as each sample contains two channels.
13
+pub const SAMPLES_PER_PACKET: usize = 48;
14
+/// Number of channels for all audio data.
15
+pub const CHANNELS: usize = 2;
16
+
17
+/// Buffer for a single packet with audio data.
18
+pub type Packet = [u32; SAMPLES_PER_PACKET * CHANNELS];
19
+
20
+/// Type for audio packet buffering.
21
+///
22
+/// The audio packets always contain two channels with 32-bit samples. The type contains a number
23
+/// of buffers each containing the same fixed number of samples.
24
+pub struct AudioBuffer<const PACKETS: usize> {
25
+    mutex: Mutex<AudioBufferInner<PACKETS>>,
26
+}
27
+
28
+struct AudioBufferInner<const PACKETS: usize> {
29
+    /// Packet contents.
30
+    packets: [UnsafeCell<Packet>; PACKETS],
31
+    /// Bitmask of packets which contain valid data and are not currently being read.
32
+    valid: Cell<u32>,
33
+    /// Bitmask of packets which do not contain valid data and which are not currently being
34
+    /// written.
35
+    invalid: Cell<u32>,
36
+    /// Bitmask of all packets which are currently borrowed via `borrow_read()`.
37
+    reading: Cell<u32>,
38
+    /// Bitmask of all packets which are currently borrowed via `borrow_write()`.
39
+    writing: Cell<u32>,
40
+}
41
+
42
+impl AudioBuffer<4> {
43
+    /// Creates a new audio buffer.
44
+    pub const fn new() -> Self {
45
+        const PACKETS: usize = 4;
46
+        // Initially, all packet contents are invalid and no packets are currently being read or
47
+        // written.
48
+        AudioBuffer {
49
+            mutex: Mutex::new(AudioBufferInner {
50
+                packets: [
51
+                    UnsafeCell::new([0; SAMPLES_PER_PACKET * CHANNELS]),
52
+                    UnsafeCell::new([0; SAMPLES_PER_PACKET * CHANNELS]),
53
+                    UnsafeCell::new([0; SAMPLES_PER_PACKET * CHANNELS]),
54
+                    UnsafeCell::new([0; SAMPLES_PER_PACKET * CHANNELS]),
55
+                ],
56
+                valid: Cell::new(0),
57
+                invalid: Cell::new(((1 << PACKETS) - 1) as u32),
58
+                reading: Cell::new(0),
59
+                writing: Cell::new(0),
60
+            }),
61
+        }
62
+    }
63
+}
64
+
65
+impl<const PACKETS: usize> AudioBuffer<PACKETS> {
66
+    /// Returns an interface to read packets from this buffer.
67
+    pub fn read(&'static self) -> ReadBuffer<PACKETS> {
68
+        ReadBuffer { buffer: self }
69
+    }
70
+
71
+    /// Returns an interface to write packets to this buffer.
72
+    pub fn write(&'static self) -> WriteBuffer<PACKETS> {
73
+        WriteBuffer { buffer: self }
74
+    }
75
+}
76
+
77
+/// Interface to read packets from a buffer.
78
+pub struct ReadBuffer<const PACKETS: usize> {
79
+    buffer: &'static AudioBuffer<PACKETS>,
80
+}
81
+
82
+impl<const PACKETS: usize> ReadBuffer<PACKETS> {
83
+    /// Returns whether there are any buffers with valid data ready for reading.
84
+    pub fn can_read(&self, cs: &CriticalSection) -> bool {
85
+        let inner = self.buffer.mutex.borrow(cs);
86
+        inner.valid.get() != 0
87
+    }
88
+
89
+    /// Borrows a single buffer for reading, returns `None` if no buffer with valid data is
90
+    /// available.
91
+    ///
92
+    /// The caller needs to return the buffer via `read_finished()` once the data has been
93
+    /// processed.
94
+    pub fn borrow_read(&self, cs: &CriticalSection) -> Option<ReadPacket<PACKETS>> {
95
+        let inner = self.buffer.mutex.borrow(cs);
96
+        let valid = inner.valid.get();
97
+        if valid == 0 {
98
+            return None;
99
+        }
100
+        let index = valid.trailing_zeros();
101
+        inner.valid.set(valid & !(1 << index));
102
+        inner.reading.set(inner.reading.get() | (1 << index));
103
+
104
+        let index = index as usize;
105
+        Some(ReadPacket {
106
+            buffer: self.buffer,
107
+            data: unsafe { &*inner.packets[index].get() },
108
+            index,
109
+        })
110
+    }
111
+
112
+    /// Returns a buffer that was allocated via `borrow_read()` and marks it as empty.
113
+    pub fn read_finished(&self, packet: ReadPacket<PACKETS>, cs: &CriticalSection) {
114
+        assert!((self.buffer as *const _) == (packet.buffer as *const _));
115
+        let inner = self.buffer.mutex.borrow(cs);
116
+        let index = packet.index;
117
+        inner.reading.set(inner.reading.get() & !(1 << index));
118
+        inner.invalid.set(inner.invalid.get() | (1 << index));
119
+    }
120
+}
121
+
122
+/// Interface to write packets to a buffer.
123
+pub struct WriteBuffer<const PACKETS: usize> {
124
+    buffer: &'static AudioBuffer<PACKETS>,
125
+}
126
+
127
+impl<const PACKETS: usize> WriteBuffer<PACKETS> {
128
+    /// Returns whether there are any empty buffers ready for writing.
129
+    pub fn can_write(&self, cs: &CriticalSection) -> bool {
130
+        let inner = self.buffer.mutex.borrow(cs);
131
+        inner.invalid.get() != 0
132
+    }
133
+
134
+    /// Borrows a single buffer for writing, returns `None` if no empty buffer is available.
135
+    ///
136
+    /// The caller needs to return the buffer via `write_finished()` once it was filled with data.
137
+    pub fn borrow_write(&self, cs: &CriticalSection) -> Option<WritePacket<PACKETS>> {
138
+        let inner = self.buffer.mutex.borrow(cs);
139
+        let invalid = inner.invalid.get();
140
+        if invalid == 0 {
141
+            return None;
142
+        }
143
+        let index = invalid.trailing_zeros();
144
+        inner.invalid.set(invalid & !(1 << index));
145
+        inner.writing.set(inner.writing.get() | (1 << index));
146
+
147
+        let index = index as usize;
148
+        Some(WritePacket {
149
+            buffer: self.buffer,
150
+            data: unsafe { &mut *inner.packets[index].get() },
151
+            index,
152
+        })
153
+    }
154
+
155
+    /// Returns a buffer that was allocated via `borrow_write()` and marks it as ready for reading.
156
+    pub fn write_finished(&self, packet: WritePacket<PACKETS>, cs: &CriticalSection) {
157
+        assert!((self.buffer as *const _) == (packet.buffer as *const _));
158
+        let inner = self.buffer.mutex.borrow(cs);
159
+        let index = packet.index;
160
+        inner.writing.set(inner.writing.get() & !(1 << index));
161
+        inner.valid.set(inner.valid.get() | (1 << index));
162
+    }
163
+}
164
+
165
+/// Packet buffer that has been borrowed for reading (i.e., the buffer contains valid data).
166
+pub struct ReadPacket<const PACKETS: usize> {
167
+    buffer: &'static AudioBuffer<PACKETS>,
168
+    data: &'static Packet,
169
+    index: usize,
170
+}
171
+
172
+impl<const PACKETS: usize> AsRef<[u32]> for ReadPacket<PACKETS> {
173
+    fn as_ref(&self) -> &[u32] {
174
+        self.data
175
+    }
176
+}
177
+
178
+impl<const PACKETS: usize> Deref for ReadPacket<PACKETS> {
179
+    type Target = Packet;
180
+
181
+    fn deref(&self) -> &Self::Target {
182
+        &self.data
183
+    }
184
+}
185
+
186
+unsafe impl<const PACKETS: usize> StableDeref for ReadPacket<PACKETS> {}
187
+
188
+/// Packet buffer that has been borrowed for writing (i.e., the buffer was previously empty).
189
+pub struct WritePacket<const PACKETS: usize> {
190
+    buffer: &'static AudioBuffer<PACKETS>,
191
+    data: &'static mut Packet,
192
+    index: usize,
193
+}
194
+
195
+impl<const PACKETS: usize> AsRef<[u32]> for WritePacket<PACKETS> {
196
+    fn as_ref(&self) -> &[u32] {
197
+        self.data
198
+    }
199
+}
200
+
201
+impl<const PACKETS: usize> AsMut<[u32]> for WritePacket<PACKETS> {
202
+    fn as_mut(&mut self) -> &mut [u32] {
203
+        self.data
204
+    }
205
+}

+ 121
- 0
src/i2s_master.rs 查看文件

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

+ 278
- 0
src/main.rs 查看文件

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

+ 66
- 0
src/usb.rs 查看文件

@@ -0,0 +1,66 @@
1
+use crate::audio_buffer::{WriteBuffer, WritePacket};
2
+use crate::usb_audio::UsbAudioClass;
3
+use rp2040_hal::pac::USBCTRL_REGS;
4
+use rp2040_hal::timer::Timer;
5
+use rp2040_hal::usb::UsbBus;
6
+use usb_device::{class_prelude::*, prelude::*};
7
+
8
+pub struct Usb {
9
+    usb_audio: UsbAudioClass<'static, UsbBus, WritePacket<4>>,
10
+    usb_dev: UsbDevice<'static, UsbBus>,
11
+    in_buffer: WriteBuffer<4>,
12
+
13
+    timer: Timer,
14
+}
15
+
16
+impl Usb {
17
+    pub fn init(
18
+        bus: &'static UsbBusAllocator<UsbBus>,
19
+        in_buffer: WriteBuffer<4>,
20
+        timer: Timer,
21
+    ) -> Usb {
22
+        let usb_audio = UsbAudioClass::new(bus);
23
+
24
+        // This PID/VID combination is selected from the pid.codes PID space and only intended for
25
+        // software development. It is not universally unique and should not be used outside of
26
+        // test environments!
27
+        let usb_dev = UsbDeviceBuilder::new(bus, UsbVidPid(0x1209, 0x000d))
28
+            .manufacturer("TEST")
29
+            .product("USB audio test")
30
+            .serial_number("TEST")
31
+            .build();
32
+
33
+        // TODO
34
+        Usb {
35
+            usb_audio,
36
+            usb_dev,
37
+            in_buffer,
38
+            timer,
39
+        }
40
+    }
41
+
42
+    pub fn poll(&mut self) {
43
+        // Safety: The read access does not have any side effect, and this function is the only one
44
+        // using the USB peripheral at this time.
45
+        let sof = unsafe { (&*USBCTRL_REGS::ptr()).intr.read().dev_sof().bit_is_set() };
46
+        if sof {
47
+            // Clear the SOF IRQ.
48
+            unsafe { (&*USBCTRL_REGS::ptr()).sof_rd.read() };
49
+
50
+            // Calculate the frequency difference (frames versus 1kHz derived from the system
51
+            // clock) and update the synchronization data for the USB audio class accordingly.
52
+            // Also, add a correction factor if the buffers are running low or high.
53
+            // TODO
54
+
55
+            /*let mut buffer = [0u8; 64];
56
+            for i in 0..64 {
57
+                buffer[i] = i as u8 * 4;
58
+            }
59
+            let _err = self.usb_audio.write_packet(&buffer);*/
60
+        }
61
+        if self.usb_dev.poll(&mut [&mut self.usb_audio]) {
62
+            // If we received audio data, move it into the buffer.
63
+            // TODO
64
+        }
65
+    }
66
+}

+ 513
- 0
src/usb_audio.rs 查看文件

@@ -0,0 +1,513 @@
1
+//! USB audio class for asynchronous, bidirectional (microphone + speakers) 48kHz audio.
2
+//!
3
+//! See "Universal Serial Bus Device Class Definition for Audio Devices", release 1.0 (March 18,
4
+//! 1998) for a specification of the USB audio class.
5
+use cortex_m::interrupt;
6
+use usb_device::class_prelude::*;
7
+use usb_device::endpoint::{IsochronousSynchronizationType, IsochronousUsageType};
8
+use usb_device::Result;
9
+
10
+const DEVICE_CLASS_AUDIO: u8 = 0x01;
11
+const AUDIO_SUBCLASS_CONTROL: u8 = 0x01;
12
+const AUDIO_SUBCLASS_STREAMING: u8 = 0x02;
13
+const AUDIO_PROTOCOL_NONE: u8 = 0x00;
14
+
15
+const AUDIO_INTERFACE_DESC_TYPE: u8 = 0x24;
16
+const AUDIO_ENDPOINT_DESC_TYPE: u8 = 0x25;
17
+
18
+const AUDIO_CONTROL_HEADER: u8 = 0x01;
19
+const AUDIO_CONTROL_INPUT_TERMINAL: u8 = 0x02;
20
+const AUDIO_CONTROL_OUTPUT_TERMINAL: u8 = 0x03;
21
+const AUDIO_CONTROL_FEATURE_UNIT: u8 = 0x06;
22
+
23
+const AUDIO_STREAMING_GENERAL: u8 = 0x01;
24
+const AUDIO_STREAMING_FORMAT_TYPE: u8 = 0x02;
25
+
26
+const AUDIO_ENDPOINT_GENERAL: u8 = 0x01;
27
+
28
+const SET_CUR: u8 = 0x01;
29
+const GET_CUR: u8 = 0x81;
30
+/*const SET_MIN: u8 = 0x02;*/
31
+const GET_MIN: u8 = 0x82;
32
+/*const SET_MAX: u8 = 0x03;*/
33
+const GET_MAX: u8 = 0x83;
34
+/*const SET_RES: u8 = 0x04;*/
35
+const GET_RES: u8 = 0x84;
36
+/*const SET_MEM: u8 = 0x05;
37
+const GET_MEM: u8 = 0x85;
38
+const GET_STAT: u8 = 0xFF;*/
39
+
40
+const MUTE_CONTROL: u8 = 0x01;
41
+const VOLUME_CONTROL: u8 = 0x02;
42
+
43
+// TODO: Update bDelay.
44
+
45
+pub struct UsbAudioClass<'a, B: UsbBus, OUTBUF: AsRef<[u32]>> {
46
+    audio_control: InterfaceNumber,
47
+    //audio_streaming_inactive: InterfaceNumber,
48
+    audio_streaming: InterfaceNumber,
49
+    audio_out: EndpointOut<'a, B>,
50
+    //audio_out_sync: EndpointIn<'a, B>,
51
+    //audio_in: EndpointIn<'a, B>,
52
+    samples_per_frame: [u8; 3],
53
+
54
+    audio_out_buf: Option<OUTBUF>,
55
+
56
+    volume: [u8; 2],
57
+    mute: u8,
58
+}
59
+
60
+impl<'a, B: UsbBus, OUTBUF: AsRef<[u32]>> UsbAudioClass<'a, B, OUTBUF> {
61
+    pub fn new(bus_alloc: &'a UsbBusAllocator<B>) -> Self {
62
+        UsbAudioClass {
63
+            audio_control: bus_alloc.interface(),
64
+            //audio_streaming_inactive: bus_alloc.interface(),
65
+            audio_streaming: bus_alloc.interface(),
66
+            // 48kHz * 2 * 16bit = 192B per packet. We allocate a bit more in case the device clock
67
+            // is faster than the host clock.
68
+            /*audio_out: bus_alloc.isochronous(
69
+                IsochronousSynchronizationType::Asynchronous,
70
+                IsochronousUsageType::Data,
71
+                256,
72
+                1,
73
+            ),*/
74
+            audio_out: bus_alloc.isochronous(
75
+                IsochronousSynchronizationType::Synchronous,
76
+                IsochronousUsageType::Data,
77
+                256,
78
+                1,
79
+            ),
80
+            /*audio_out_sync: bus_alloc.isochronous(
81
+                IsochronousSynchronizationType::Asynchronous,
82
+                IsochronousUsageType::Feedback,
83
+                3,
84
+                1,
85
+            ),*/
86
+            /*audio_in: bus_alloc.isochronous(
87
+                IsochronousSynchronizationType::Asynchronous,
88
+                IsochronousUsageType::Data,
89
+                256,
90
+                1,
91
+            ),*/
92
+            samples_per_frame: [48 >> 2, 48 << 6, 0], // 48 kHz
93
+            audio_out_buf: None,
94
+
95
+            volume: [1, 0],
96
+            mute: 0,
97
+        }
98
+    }
99
+
100
+    // TODO: Functions to read and write data?
101
+}
102
+
103
+impl<B: UsbBus, OUTBUF: AsRef<[u32]>> UsbClass<B> for UsbAudioClass<'_, B, OUTBUF> {
104
+    fn get_configuration_descriptors(&self, writer: &mut DescriptorWriter) -> Result<()> {
105
+        /*interrupt::free(|cs| {
106
+            writeln!(crate::uart(cs), "A\r").unwrap();
107
+        });*/
108
+        writer.iad(
109
+            self.audio_control,
110
+            2,   // Two interfaces (control + streaming).
111
+            0x0, // Each interface specifies its own class.
112
+            0x0, // Each interface specifies its own subclass.
113
+            0x0, // No class-specific protocols for this device.
114
+        )?;
115
+
116
+        // Audio control interface.
117
+        writer.interface(
118
+            self.audio_control,
119
+            DEVICE_CLASS_AUDIO,
120
+            AUDIO_SUBCLASS_CONTROL,
121
+            AUDIO_PROTOCOL_NONE,
122
+        )?;
123
+
124
+        writer.write(
125
+            AUDIO_INTERFACE_DESC_TYPE,
126
+            &[
127
+                AUDIO_CONTROL_HEADER,        // bDescriptorSubtype
128
+                0x00,                        // bcdADC
129
+                0x01,                        //
130
+                37,                          // wTotalLength
131
+                0,                           //
132
+                0x01,                        // bInCollection
133
+                self.audio_streaming.into(), // baInterfaceNr
134
+            ],
135
+        )?;
136
+
137
+        // Input terminal (USB streaming).
138
+        writer.write(
139
+            AUDIO_INTERFACE_DESC_TYPE,
140
+            &[
141
+                AUDIO_CONTROL_INPUT_TERMINAL, // bDescriptorSubtype
142
+                0x01,                         // bTerminalID
143
+                0x01,                         // wTerminalType
144
+                0x01,                         //
145
+                0x00,                         // bAssocTerminal
146
+                0x02,                         // bNrChannels
147
+                0x03,                         // wChannelConfig
148
+                0x00,                         //
149
+                0x00,                         // iChannelNames
150
+                0x00,                         // iTerminal
151
+            ],
152
+        )?;
153
+
154
+        // Feature unit (volume and mute).
155
+        writer.write(
156
+            AUDIO_INTERFACE_DESC_TYPE,
157
+            &[
158
+                AUDIO_CONTROL_FEATURE_UNIT, // bDescriptorSubtype
159
+                0x02,                       // bUnitID
160
+                0x01,                       // bSourceID
161
+                0x01,                       // bControlSize
162
+                0x03,                       // bmaControls(0)
163
+                0x00,                       // iFeature
164
+            ],
165
+        )?;
166
+
167
+        // Output terminal (speaker).
168
+        writer.write(
169
+            AUDIO_INTERFACE_DESC_TYPE,
170
+            &[
171
+                AUDIO_CONTROL_OUTPUT_TERMINAL, // bDescriptorSubtype
172
+                0x03,                          // bTerminalID
173
+                0x01,                          // wTerminalType
174
+                0x03,                          //
175
+                0x00,                          // bAssocTerminal
176
+                0x02,                          // bSourceID
177
+                0x00,                          // iTerminal
178
+            ],
179
+        )?;
180
+
181
+        // Audio streaming interface (zero-bandwidth).
182
+        writer.interface(
183
+            self.audio_streaming,
184
+            DEVICE_CLASS_AUDIO,
185
+            AUDIO_SUBCLASS_STREAMING,
186
+            AUDIO_PROTOCOL_NONE,
187
+        )?;
188
+
189
+        // Audio streaming interface (operational).
190
+        writer.interface_alt(
191
+            self.audio_streaming,
192
+            1,
193
+            DEVICE_CLASS_AUDIO,
194
+            AUDIO_SUBCLASS_STREAMING,
195
+            AUDIO_PROTOCOL_NONE,
196
+            None,
197
+        )?;
198
+
199
+        writer.write(
200
+            AUDIO_INTERFACE_DESC_TYPE,
201
+            &[
202
+                AUDIO_STREAMING_GENERAL, // bDescriptorSubtype
203
+                0x01,                    // bTerminalLink
204
+                0x03,                    // bDelay
205
+                0x01,                    // wFormatTag
206
+                0x00,                    //
207
+            ],
208
+        )?;
209
+
210
+        writer.write(
211
+            AUDIO_INTERFACE_DESC_TYPE,
212
+            &[
213
+                AUDIO_STREAMING_FORMAT_TYPE, // bDescriptorSubtype
214
+                0x01,                        // bFormatType
215
+                0x02,                        // bNrChannels
216
+                0x02,                        // bSubframeSize
217
+                0x10,                        // bBitResolution
218
+                0x01,                        // bSamFreqType
219
+                0x80,                        // tSamFreq[1]
220
+                0xbb,                        //
221
+                0x00,                        //
222
+            ],
223
+        )?;
224
+
225
+        /*writer.endpoint_ex(&self.audio_out, |data| {
226
+            // TODO: Faster refresh
227
+            data[0] = 0x09; // bRefresh
228
+            data[1] = self.audio_out_sync.address().into(); // bSynchAddress
229
+            Ok(2)
230
+        })?;*/
231
+        writer.endpoint(&self.audio_out)?;
232
+
233
+        writer.write(
234
+            AUDIO_ENDPOINT_DESC_TYPE,
235
+            &[
236
+                AUDIO_ENDPOINT_GENERAL, // bDescriptorSubtype
237
+                0x00,                   // bmAttributes
238
+                0x01,                   // bLockDelayUnits
239
+                0x00,                   // wLockDelay
240
+                0x00,
241
+            ],
242
+        )?;
243
+
244
+        /*writer.endpoint_ex(&self.audio_out_sync, |data| {
245
+            data[0] = 0x00; // bRefresh
246
+            data[1] = 0x00; // bSynchAddress
247
+            Ok(2)
248
+        })?;*/
249
+
250
+        /*interrupt::free(|cs| {
251
+            writeln!(crate::uart(cs), "B\r").unwrap();
252
+        });*/
253
+
254
+        Ok(())
255
+    }
256
+
257
+    fn get_string(&self, _index: StringIndex, _lang_id: u16) -> Option<&str> {
258
+        // TODO
259
+        None
260
+    }
261
+
262
+    fn reset(&mut self) {
263
+        // Start sending synchronization data.
264
+        //self.endpoint_in_complete(self.audio_out_sync.address());
265
+    }
266
+
267
+    fn control_out(&mut self, xfer: ControlOut<B>) {
268
+        let req = xfer.request();
269
+
270
+        // TODO: Alternate interfaces?
271
+        if req.request_type == control::RequestType::Standard
272
+            && req.recipient == control::Recipient::Interface
273
+            && req.request == control::Request::SET_INTERFACE
274
+        {
275
+            // TODO
276
+            xfer.accept().ok();
277
+            return;
278
+        }
279
+
280
+        // We only support interface requests.
281
+        if req.request_type != control::RequestType::Class
282
+            || req.recipient != control::Recipient::Interface
283
+        {
284
+            return;
285
+        }
286
+
287
+        let interface = req.index & 0xff;
288
+        let entity = req.index >> 8;
289
+
290
+        if interface != u8::from(self.audio_control) as u16 {
291
+            return;
292
+        }
293
+
294
+        if entity != 0x2 {
295
+            xfer.reject().ok();
296
+            return;
297
+        }
298
+
299
+        /*if !(req.request_type == control::RequestType::Class
300
+            && req.recipient == control::Recipient::Interface
301
+            && req.index == u8::from(self.audio_control) as u16)
302
+        {
303
+            return;
304
+        }*/
305
+
306
+        match req.request {
307
+            SET_CUR => {
308
+                let control_selector = (req.value >> 8) as u8;
309
+                let channel_number = req.value & 0xff;
310
+
311
+                match control_selector {
312
+                    MUTE_CONTROL if xfer.data().len() == 1 => {
313
+                        // TODO: Channel?
314
+                        self.mute = xfer.data()[0];
315
+                        xfer.accept().ok();
316
+                    }
317
+                    VOLUME_CONTROL if xfer.data().len() == 2 => {
318
+                        // TODO: Channel?
319
+                        self.volume[0] = xfer.data()[0];
320
+                        self.volume[1] = xfer.data()[1];
321
+                        xfer.accept().ok();
322
+                    }
323
+                    _ => {
324
+                        xfer.reject().ok();
325
+                    }
326
+                }
327
+            }
328
+            _ => {
329
+                xfer.reject().ok();
330
+            }
331
+        };
332
+    }
333
+
334
+    fn control_in(&mut self, xfer: ControlIn<B>) {
335
+        let req = xfer.request();
336
+
337
+        // We only support interface requests.
338
+        if req.request_type != control::RequestType::Class
339
+            || req.recipient != control::Recipient::Interface
340
+        {
341
+            return;
342
+        }
343
+
344
+        let interface = req.index & 0xff;
345
+        let entity = req.index >> 8;
346
+
347
+        if interface != u8::from(self.audio_control) as u16 {
348
+            return;
349
+        }
350
+
351
+        if entity != 0x2 {
352
+            xfer.reject().ok();
353
+            return;
354
+        }
355
+
356
+        /*if !(req.request_type == control::RequestType::Class
357
+            && req.recipient == control::Recipient::Interface
358
+            && req.index == u8::from(self.audio_control) as u16)
359
+        {
360
+            return;
361
+        }*/
362
+
363
+        match req.request {
364
+            GET_MIN => {
365
+                let control_selector = (req.value >> 8) as u8;
366
+                let channel_number = req.value & 0xff;
367
+
368
+                match control_selector {
369
+                    MUTE_CONTROL => {
370
+                        if channel_number == 0xff && req.length == 2 {
371
+                            // TODO
372
+                            xfer.accept_with(&[0, 0]).ok();
373
+                        } else if channel_number != 0xff && req.length == 1 {
374
+                            // TODO
375
+                            xfer.accept_with(&[0]).ok();
376
+                        } else {
377
+                            xfer.reject().ok();
378
+                        }
379
+                    }
380
+                    VOLUME_CONTROL => {
381
+                        if channel_number == 0xff && req.length == 4 {
382
+                            // TODO
383
+                            xfer.accept_with(&[0x00, 0x00, 0x00, 0x00]).ok();
384
+                        } else if channel_number != 0xff && req.length == 2 {
385
+                            // TODO
386
+                            xfer.accept_with(&[0x00, 0x00]).ok();
387
+                        } else {
388
+                            xfer.reject().ok();
389
+                        }
390
+                    }
391
+                    _ => {
392
+                        xfer.reject().ok();
393
+                    }
394
+                }
395
+            }
396
+            GET_MAX => {
397
+                let control_selector = (req.value >> 8) as u8;
398
+                let channel_number = req.value & 0xff;
399
+
400
+                match control_selector {
401
+                    MUTE_CONTROL => {
402
+                        if channel_number == 0xff && req.length == 2 {
403
+                            // TODO
404
+                            xfer.accept_with(&[1, 1]).ok();
405
+                        } else if channel_number != 0xff && req.length == 1 {
406
+                            // TODO
407
+                            xfer.accept_with(&[1]).ok();
408
+                        } else {
409
+                            xfer.reject().ok();
410
+                        }
411
+                    }
412
+                    VOLUME_CONTROL => {
413
+                        if channel_number == 0xff && req.length == 4 {
414
+                            // TODO
415
+                            xfer.accept_with(&[0x00, 0x01, 0x00, 0x01]).ok();
416
+                        } else if channel_number != 0xff && req.length == 2 {
417
+                            // TODO
418
+                            xfer.accept_with(&[0x00, 0x01]).ok();
419
+                        } else {
420
+                            xfer.reject().ok();
421
+                        }
422
+                    }
423
+                    _ => {
424
+                        xfer.reject().ok();
425
+                    }
426
+                }
427
+            }
428
+            GET_RES => {
429
+                let control_selector = (req.value >> 8) as u8;
430
+                let channel_number = req.value & 0xff;
431
+
432
+                match control_selector {
433
+                    VOLUME_CONTROL => {
434
+                        if channel_number == 0xff && req.length == 4 {
435
+                            // TODO
436
+                            xfer.accept_with(&[0x01, 0x00, 0x01, 0x00]).ok();
437
+                        } else if channel_number != 0xff && req.length == 2 {
438
+                            // TODO
439
+                            xfer.accept_with(&[0x01, 0x00]).ok();
440
+                        } else {
441
+                            xfer.reject().ok();
442
+                        }
443
+                    }
444
+                    _ => {
445
+                        xfer.reject().ok();
446
+                    }
447
+                }
448
+            }
449
+            GET_CUR => {
450
+                let control_selector = (req.value >> 8) as u8;
451
+                let channel_number = req.value & 0xff;
452
+
453
+                match control_selector {
454
+                    MUTE_CONTROL => {
455
+                        if channel_number == 0xff && req.length == 2 {
456
+                            // TODO
457
+                            xfer.accept_with(&[self.mute, self.mute]).ok();
458
+                        } else if channel_number != 0xff && req.length == 1 {
459
+                            // TODO
460
+                            xfer.accept_with(&[self.mute]).ok();
461
+                        } else {
462
+                            xfer.reject().ok();
463
+                        }
464
+                    }
465
+                    VOLUME_CONTROL => {
466
+                        if channel_number == 0xff && req.length == 4 {
467
+                            // TODO
468
+                            xfer.accept_with(&[
469
+                                self.volume[0],
470
+                                self.volume[1],
471
+                                self.volume[0],
472
+                                self.volume[1],
473
+                            ])
474
+                            .ok();
475
+                        } else if channel_number != 0xff && req.length == 2 {
476
+                            // TODO
477
+                            xfer.accept_with(&self.volume).ok();
478
+                        } else {
479
+                            xfer.reject().ok();
480
+                        }
481
+                    }
482
+                    _ => {
483
+                        xfer.reject().ok();
484
+                    }
485
+                }
486
+            }
487
+            // TODO
488
+            _ => {
489
+                xfer.reject().ok();
490
+            }
491
+        };
492
+    }
493
+
494
+    fn endpoint_out(&mut self, addr: EndpointAddress) {
495
+        if addr == self.audio_out.address() {
496
+            if self.audio_out_buf.is_some() {
497
+                // TODO: Write data into buffer, move buffer somewhere else.
498
+            } else {
499
+                // TODO
500
+            }
501
+            // TODO: Process incoming audio data.
502
+            let mut buffer = [0u8; 256];
503
+            self.audio_out.read(&mut buffer).ok();
504
+        }
505
+    }
506
+
507
+    fn endpoint_in_complete(&mut self, addr: EndpointAddress) {
508
+        /*if addr == self.audio_out_sync.address() {
509
+            // Immediately write the next sync value.
510
+            //self.audio_out_sync.write(&self.samples_per_frame).unwrap();
511
+        }*/
512
+    }
513
+}

正在加载...
取消
保存