RT600/1170 UAC change OUT endpoint interval methods

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

RT600/1170 UAC change OUT endpoint interval methods

RT600/1170 UAC change OUT endpoint interval methods

1.    Abstract

When using the RT600 SDK USB composite example, the customer found that the default HS interval was 125us, and the code was: mimxrt685audevk_dev_composite_hid_audio_unified_bm.

However, in actual applications, the 125us packet interval for data transmission will cause a large interrupt load on the CPU, so the customer hopes to change the interval to a larger during, such as 1ms. After changing interval to 1ms, it is found that the data packet can be sent to the RT chip, but there is indeed a problem with the playback on the RT side, speaker no voice. Changing it to 500us in synchronous mode is possible work, but at 500us, the customer's CPU load still reaches more than 80%, which is not convenient for subsequent application code expansion, so it is still hoped to achieve a 1ms method.

This article will give the transmission of different intervals of UAC and provide a solution for 1ms intervals.

2.    Test situation

   Board:MIMXRT685-AUD-EVK

   SDK:SDK_2_15_000_MIMXRT685-AUD-EVK

   USB Analyzer:Lecroy USB-TOS2-A01-X

2.1 Platform connection situation

First, given the connection between MIMXRT685-AUD-EVK, USB analyzer and audio source. This article mainly tests the RT685 UAC speaker function, that is, USB transmits audio source data to RT685, and plays the audio source through a player (which can be headphones), or speaker. The J7 USB port of EVK is connected to the A port of Lecroy, and the B port of Lecroy is connected to the audio source, which can be a PC or a mobile phone. If using a PC, the speaker needs to be selected as USB AUDIO+HID DEMO, because the name of the board after UAC enumeration is USB AUDIO+HID DEMO.

The other end of Lecroy is connected to the PC for transmitting USB bus data. The specific connection diagram is as follows:   

 1.jpg

Fig 1 EVK USB analyzer connection

2.2 Different audio interval data package situation

This chapter gives the modifications under different intervals, as well as the results of USB analyzer packet capture. The clock system of the audio synchronous/isochronous audio endpoint can be synchronized through SOF. The USB 1.0 sampling rate must be locked to the 1ms SOF beat. The USB2.0 high-speed HS endpoint can be locked to the 125us SOF beat. If you want to change the interval, it is usually a multiple of 125us, that is, it can be 250us, 500us, 1ms, etc. The modification method is usually to directly modify the USB stack's usb_audio_config.h:  

#define HS_ISO_OUT_ENDP_INTERVAL (0x01)

The relationship between HS_ISO_OUT_ENDP_INTERVAL and the real during time is: 125us*2^( HS_ISO_OUT_ENDP_INTERVAL -1)

So:

HS_ISO_OUT_ENDP_INTERVAL=1 :  125us
HS_ISO_OUT_ENDP_INTERVAL=2 :  250us
HS_ISO_OUT_ENDP_INTERVAL=3 :  500us
HS_ISO_OUT_ENDP_INTERVAL=4 :  1000us

The following are the four situations mentioned above respectively through USB analyzer packet capture test.

2.2.1 125us interval packet situation

#define HS_ISO_OUT_ENDP_INTERVAL (0x01)

2.jpg

Fig 2 125us interval

It can be seen that when the interval is configured to 125us, the SOF beat interval in front of each OUT packet is 125us, and the length of the OUT data packet is 24Byte. The data in this 24Byte packet is the actual audio data.

In this case, the playback is normal  

2.2.2 250us interval packet situation

  #define HS_ISO_OUT_ENDP_INTERVAL (0x02)

The packet capture configured as 250us is shown in the figure below. It can be seen that the SOF beat interval in front of the two OUT packets is 250us, and the length of the OUT data packet is 48 Byte. In other words, as the interval increases, the length of the data packet also increases proportionally, that is, the transmission time is longer, but a packet contains more data packets. At this time, the RT side also needs to provide more USB receiving buffers to receive data.

3.jpg

Fig 3 250us interval

This situation, the speaker play normally, have the audio sound.

2.2.3 500us interval packet situation

#define HS_ISO_OUT_ENDP_INTERVAL (0x03)

4.jpg

Fig 4 500us interval SYNC mode

At this time, you can see that the data packet has become 96 Bytes, and the data content is also normal audio data, but the playback has problems and no sound can be heard.

However, if you configure:

#define USB_DEVICE_AUDIO_USE_SYNC_MODE (0U)

It is not the SYNC mode, it can hear the audio sound, the packet situation is:

5.jpg

Fig 5 500us interval no SYNC mode

However, the asynchronous mode also has problems. After a long period of operation, it may become out of sync and the playback may become stuck. Therefore, it is still necessary to use the 1ms method in the synchronous mode.

2.2.4 1ms interval packet situation

#define HS_ISO_OUT_ENDP_INTERVAL (0x04)

6.jpg

Fig 6 interval 1ms

It can be seen that the data packet length has become 192 bytes, and the SOF beat interval in front of the OUT packet has indeed become 1ms. The audio data packet also looks like normal audio data, so the audio data here is successfully transmitted from USB to RT. However, the playback is abnormal and no sound can be heard.

3. 1ms interval solution

Now let's debug the project to find the problem. Because the USB analyzer can show that the audio data of the USB bus is actually transmitted, we must first check whether the USB receives the data packet in the kUSB_DeviceAudioEventStreamRecvResponse event in USB_DeviceAudioCompositeCallback of audio_unified.c, whether the data packet length is correct, and whether the data content looks like audio data. The following is the debug result:

7.jpg

Fig 7 data packet received situation

So from this point of view, the USB interface data packet is received, and the data looks like real audio data. If it is abnormal data, it is either all 0 or irregular data that changes, but the test result cannot be played.

So now to check the I2S playback function, composite.h file, TxCallback function:

8.jpg

Fig 8 I2S play data buffer

We can see, the real data transfer to the I2S data buffer are always 0, and the reality should be

g_composite.audioUnified.startPlayFlag none zero, and also use:

s_TxTransfer.dataSize = g_composite.audioUnified.audioPlayTransferSize;
s_TxTransfer.data=audioPlayDataBuff + g_composite.audioUnified.tdReadNumberPlay;

But, after testing, audioPlayDataBuff data are also 0. So the issue should be the USB received side, receive the data, but when save the data to the audioPlayDataBuff have issues, go back to audio_unified.c

9.jpg

Fig 9 USB_DeviceAudioCompositeCallback

10.jpg

Fig10 USB_AudioSpeakerPutBuffer

After testing, in the Fig 9, audioUnified.tdWriteNumberPlay never larger than

g_deviceAudioComposite->audioUnified.audioPlayTransferSize * AUDIO_CLASS_2_0_HS_LOW_LATENCY_TRANSFER_COUNT=192*6

 

#define AUDIO_CLASS_2_0_HS_LOW_LATENCY_TRANSFER_COUNT \
(0x06U) /* 6 means 6 mico frames (6*125us), make sure the latency is smaller than 1ms for sync mode */

The low latency here is a delay buffer. Therefore, the USB cache data must at least be able to hold the delayed data packet. Unit 1 represents an interval frame. Now it is changed to an interval of 1ms, 6 delay units, which means that the delay here is 6ms. Here, the receiving buffer size needs to be larger, which is related to the following definition:

11.jpg

Fig 11 USB device callback

g_composite.audioUnified.audioPlayBufferSize =
AUDIO_PLAY_BUFFER_SIZE_ONE_FRAME * AUDIO_SPEAKER_DATA_WHOLE_BUFFER_COUNT;

#define AUDIO_PLAY_BUFFER_SIZE_ONE_FRAME AUDIO_OUT_TRANSFER_LENGTH_ONE_FRAME

#define AUDIO_OUT_FORMAT_CHANNELS (0x02U)
#define AUDIO_OUT_FORMAT_SIZE     (0x02)
#define AUDIO_OUT_SAMPLING_RATE_KHZ (48)
/* transfer length during 1 ms */

#define AUDIO_OUT_TRANSFER_LENGTH_ONE_FRAME \
    (AUDIO_OUT_SAMPLING_RATE_KHZ * AUDIO_OUT_FORMAT_CHANNELS * AUDIO_OUT_FORMAT_SIZE)

#define AUDIO_SPEAKER_DATA_WHOLE_BUFFER_COUNT \
    (2U) /* 2 units size buffer (1 unit means the size to play during 1ms) */

Here, try to set larger AUDIO_SPEAKER_DATA_WHOLE_BUFFER_COUNT, let it should be at least can put 6ms data, as 1 unit is 1ms play data size, and it needs to have more than 6ms, so, set to 12 unit, the modified definition:

#define AUDIO_SPEAKER_DATA_WHOLE_BUFFER_COUNT 12

Build the project and download it, now capture the USB bus data again:

12.jpg

Fig 12 1ms interval data packet play successfully

 

This data waveform is the data that can be played normally.

Below is the video of the MIMXRT685-AUD-EVK test.

The attachment provides two demos of RT685 and RT1170, both modified to 1ms interval, and the modification method of RT1170 is exactly the same

4.    Summarize

Whether it is RT600, RT1170, or more precisely the UAC code of the entire RT series, if you need to modify the interval, the main focus is on the following macros in usb_audio_config.h, the following is for 1ms interval:

#define HS_ISO_OUT_ENDP_INTERVAL (0x04)//(0x01)//(0X04)

#define AUDIO_CLASS_2_0_HS_LOW_LATENCY_TRANSFER_COUNT \
    (0x06U) /* 6 means 16 mico frames (6*125us), make sure the latency is smaller than 1ms for ehci high speed */

#define AUDIO_SPEAKER_DATA_WHOLE_BUFFER_COUNT \
    (12U)//(2U) /* 2 units size buffer (1 unit means the size to play during 1ms) */

Test video:

Labels (2)
Attachments
Comments

Thanks so much for my colleague  @tim_wang and @jia_guo endless help!

No ratings
Version history
Last update:
2 weeks ago
Updated by: