Dicklessgreat / daisy-embassy

5 stars 2 forks source link

add usb audio example #12

Closed Dicklessgreat closed 1 month ago

Dicklessgreat commented 2 months ago

from https://github.com/embassy-rs/embassy/pull/3212 and https://github.com/elagil/embassy/blob/feat_usb_prepare_for_uac/examples/stm32f4/src/bin/usb_uac_speaker.rs

changes from STM32F4 example:

not yet works, just quick trying it out for a bit.

elagil commented 2 months ago

If you are testing this, my own implementation is for STM32H723: https://github.com/blus-audio/firmware-rs See especially https://github.com/blus-audio/firmware-rs/blob/main/firmware/src/usb_audio.rs

It requires this, though: https://github.com/embassy-rs/stm32-data/pull/511 Otherwise, the USB_SOF signal is not available on the timer, because it uses the wrong set of registers. You have to check, which timers actually have the USB_SOF signal available to them, it could be that TIM2 is the only one.

Dicklessgreat commented 2 months ago

Thanks for your answer. I did:

elagil commented 2 months ago

That looks exactly like what I was doing. It seems to not find that vector table section in your linker file, but I don't know why that would be the case. Is it building for the right target (arm)?

You don't have to use my stm32-data if you don't enable feedback. It's fine to run without feedback, but you will get an occasional glitch. Maybe that is a g good first step?

An unrelated thing in your Cargo.toml: you cannot use time-driver-tim2 if you want to use it as the feedback timer. I guess that's why you switched the feedback timer to tim5.

Dicklessgreat commented 2 months ago

It is for the right target, I think, I have run examples with this settings for many times.

If I do comment out specifying local metapac and comment in as embassy do in embassy/embassy-stm32/Cargo.toml, I mean...:

stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-e0cfd165fd8fffaa0df66a35eeca83b228496645" }
# stm32-metapac = { path = "../../stm32-data/build/stm32-metapac" }

then it is buildable...

But anyway, I'll try the "good first step" later! Thanks!

elagil commented 2 months ago

If i remember correctly, I had to change the metapac in two places in the Cargo.toml, but maybe you already did.

Good luck!

Dicklessgreat commented 2 months ago

OK, now my Windows recognizes the device as a "speaker"! I haven't checked if it really sounds well or not. I'll try again tomorrow!

Dicklessgreat commented 1 month ago

current status: It is now possible to receive audio from the host and output what appears to be that audio through the SAI. But as expected, it does not works well, because audio buffer from USB is exhausted while SAI is running, which makes short "glitches" to the output audio(if I understand correctly).

I'll check if the passing audio buffer from USB task to audio receiver really works (I'll check the detail of blus-audio's firmware). And after that, I'll try patched metapac , but I have to tuckle the error: rustc-LLVM ERROR: Global variable '__INTERRUPTS' has an invalid section specifier '.vector_table.interrupts' I found this and tried [workspace] resolver="2", but same error. https://github.com/embassy-rs/embassy/issues/1165 I don't know where this error comes from...

elagil commented 1 month ago

Not sure about the build issue, because I am not using a workspace.

Regarding the glitches, that is expected without active feedback, because the rates of receiving and consuming don't match. For transferring data between the USB streaming task and the SAI task, I had good results with a zerocopy-channel. You will find that in the blus-audio firmware, or in the example that I wrote for embassy (STM32F4).

Dicklessgreat commented 1 month ago

It turns out that rustc-LLVM ERROR comes from I missed to add default-features = false, features = ["metadata"] to the stm32-metapac in [build-dependencies] of the local embassy-stm32/Cargo.toml. OUCH!!

Dicklessgreat commented 1 month ago

from RM0433 "Reference Manual" P.1682 Table338 (STM32H742, STM32H743/753 and STM32H750 Value line advanced Arm ® -based 32-bit MCUs) image

Dicklessgreat commented 1 month ago

There are still glitches in output audio from SAI.

I found use_feedback_task infinitely do await for the connection. So feedback not yet works. Hmm, I have no idea to solve. Do you have any ideas? @elagil

I checked TIM2 interrupt and control task is working(by adding info! macro and checking defmt output). sampling rate of SAI: 48000Hz audio block length: 32(samples per channel)

elagil commented 1 month ago

That is strange. Are you on Windows or Linux? If the latter, can you show lsusb -d 0xdead:0xbeef -v for me to check if the descriptors are correct?

You may also look at dmesg, it can give hints for issues with the USB device.

Regarding the audio block length, I don't quite understand. You will get blocks of (around) 1 ms of stereo samples at 48 kHz, which is 48 (stereo) samples per ms -> 384 byte. You may get even more samples than that when the feedback mechanism indicates a consumption rate above 48 kHz. So, you should probably allow for a bigger audio block length.

Then, you are only allowing for a timeout of 500 micro seconds for receiving samples in the audio_receiver_task. Samples in USB full-speed arrive at a fixed spacing of 1 ms, so that will not work. You should allow for maybe 2 ms of timeout - but definitely more than 1 ms.

Dicklessgreat commented 1 month ago

Thanks for your feedback!

Sorry, I missed some logs from debug probe. Let me correct current state. The feedback is properly connected, but endpoint is stucked. So the feedback loop infinitely await at the second loop of feedback.write_packet(&packet).await?; here. I don't know how feedback should work but I think feedback should be periodically feed to host during the playback, right?

I'm using Windows. So I did usbipd wsl attach --busid x-x on Windows Power Shell to pass the device to WSL, and did the command you suggested.

lsusb -d 0xdead:0xbeef -v

Bus 001 Device 002: ID dead:beef Embassy USB-audio-speaker example
Couldn't open device, some information will be missing
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.10
  bDeviceClass          239 Miscellaneous Device
  bDeviceSubClass         2
  bDeviceProtocol         1 Interface Association
  bMaxPacketSize0        64
  idVendor           0xdead
  idProduct          0xbeef
  bcdDevice            0.10
  iManufacturer           1
  iProduct                2
  iSerial                 3
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x007f
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              100mA
    Interface Association:
      bLength                 8
      bDescriptorType        11
      bFirstInterface         0
      bInterfaceCount         2
      bFunctionClass          1 Audio
      bFunctionSubClass       1 Control Device
      bFunctionProtocol       0
      iFunction               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      1 Control Device
      bInterfaceProtocol      0
      iInterface              0
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      1 (HEADER)
        bcdADC               1.00
        wTotalLength       0x0028
        bInCollection           1
        baInterfaceNr(0)        1
      AudioControl Interface Descriptor:
        bLength                12
        bDescriptorType        36
        bDescriptorSubtype      2 (INPUT_TERMINAL)
        bTerminalID             1
        wTerminalType      0x0101 USB Streaming
        bAssocTerminal          0
        bNrChannels             2
        wChannelConfig     0x0003
          Left Front (L)
          Right Front (R)
        iChannelNames           0
        iTerminal               0
      AudioControl Interface Descriptor:
        bLength                10
        bDescriptorType        36
        bDescriptorSubtype      6 (FEATURE_UNIT)
        bUnitID                 2
        bSourceID               1
        bControlSize            1
        bmaControls(0)       0x00
        bmaControls(1)       0x03
          Mute Control
          Volume Control
        bmaControls(2)       0x03
          Mute Control
          Volume Control
        iFeature                0
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (OUTPUT_TERMINAL)
        bTerminalID             3
        wTerminalType      0x0301 Speaker
        bAssocTerminal          0
        bSourceID               2
        iTerminal               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0
      iInterface              0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       1
      bNumEndpoints           2
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0
      iInterface              0
      AudioStreaming Interface Descriptor:
        bLength                 7
        bDescriptorType        36
        bDescriptorSubtype      1 (AS_GENERAL)
        bTerminalLink           1
        bDelay                  0 frames
        wFormatTag         0x0001 PCM
      AudioStreaming Interface Descriptor:
        bLength                11
        bDescriptorType        36
        bDescriptorSubtype      2 (FORMAT_TYPE)
        bFormatType             1 (FORMAT_TYPE_I)
        bNrChannels             2
        bSubframeSize           4
        bBitResolution         32
        bSamFreqType            1 Discrete
        tSamFreq[ 0]        48000
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            5
          Transfer Type            Isochronous
          Synch Type               Asynchronous
          Usage Type               Data
        wMaxPacketSize     0x0300  1x 768 bytes
        bInterval               1
        bRefresh                0
        bSynchAddress         129
        AudioStreaming Endpoint Descriptor:
          bLength                 7
          bDescriptorType        37
          bDescriptorSubtype      1 (EP_GENERAL)
          bmAttributes         0x01
            Sampling Frequency
          bLockDelayUnits         2 Decoded PCM samples
          wLockDelay         0x0000
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes           17
          Transfer Type            Isochronous
          Synch Type               None
          Usage Type               Feedback
        wMaxPacketSize     0x0004  1x 4 bytes
        bInterval               1
        bRefresh                3
        bSynchAddress           0

dmesg | grep usb(and omit some unrelevant messages)


[   51.505104] usb 1-1: new full-speed USB device number 2 using vhci_hcd
[   51.855109] usb 1-1: SetAddress Request (2) to port 0
[   52.084792] usb 1-1: not running at top speed; connect to a high speed hub
[   52.173119] usb 1-1: New USB device found, idVendor=dead, idProduct=beef, bcdDevice= 0.10
[   52.173124] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[   52.173132] usb 1-1: Product: USB-audio-speaker example
[   52.173136] usb 1-1: Manufacturer: Embassy
[   52.173139] usb 1-1: SerialNumber: 12345678

BTW, the dmesg results reminded me that your example on the STM32F4 was USB "FS", and blus-audio was doing USB "HS". Although your main field is "HS", you would assume this example works with USB FS, right? (Daisy Seed has only a USB FS port.) I ask just for the confirmation!:)

Dicklessgreat commented 1 month ago

And about audio callback, sorry I didn't clearly say I'm suspicious about my current settings(that's why I wrote it). But your answer really hits what I want to ask! Thanks. I'll try fix after my works! I'll be back after finishing my daily tasks.

Dicklessgreat commented 1 month ago

In relation to other committers' PRs, I will close this PR for now, but I plan to open a new issue and reopen it at a later time.

elagil commented 1 month ago

@Dicklessgreat I didn't see your high-speed vs. full-speed question. This is only expected to work correctly with full-speed USB, as UAC 1.0 is specified for USB 1.0/1.1.

In fact, I use my HS phy in FS mode.

Dicklessgreat commented 1 month ago

In fact, I use my HS phy in FS mode.

I didn't know that's possible! And I missed it's in FS mode.

I didn't see your high-speed vs. full-speed question.

Never mind! Just I wondered if it really works on my device!

Let me correct current state. The feedback is properly connected, but endpoint is stucked. So the feedback loop infinitely await at the second loop of feedback.write_packet(&packet).await?; here.

And do you have any ideas about this? Not yet commited but in local, I tried to expand SAI callback length, and to expand zerocopy's timeout period to 2ms, but had no luck. Thanks

elagil commented 1 month ago

I didn't know that's possible! And I missed it's in FS mode.

It is, as of recently :smile:: https://github.com/embassy-rs/embassy/pull/3281 I had to add support for it, because it didn't work correctly on Windows in high-speed mode. I am not sure why.

And do you have any ideas about this?

Are you sure it's stuck there and not waiting for the signal? I don't know why it would get stuck, except if the host doesn't poll the endpoint. I will test on Windows again.