Skip to content

Commit

Permalink
Merge pull request #2259 from HiFiPhile/uac_interl
Browse files Browse the repository at this point in the history
Fix UAC encoding, update example.
  • Loading branch information
PanRe authored Oct 11, 2023
2 parents 513ab37 + c8430f5 commit 118823c
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 144 deletions.
5 changes: 5 additions & 0 deletions examples/device/audio_4_channel_mic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ target_include_directories(${PROJECT} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)

# Add libm for GCC
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_libraries(${PROJECT} PUBLIC m)
endif()

# Configure compilation flags and libraries for the example without RTOS.
# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
family_configure_device_example(${PROJECT} noos)
5 changes: 4 additions & 1 deletion examples/device/audio_4_channel_mic/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ INC += \
$(TOP)/hw \

# Example source
EXAMPLE_SOURCE += $(wildcard src/*.c)
EXAMPLE_SOURCE += \
src/main.c \
src/usb_descriptors.c \

SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))

include ../../rules.mk
1 change: 1 addition & 0 deletions examples/device/audio_4_channel_mic/skip.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mcu:SAMD11
mcu:SAME5X
mcu:SAMG
family:broadcom_64bit
58 changes: 36 additions & 22 deletions examples/device/audio_4_channel_mic/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,16 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#include "bsp/board_api.h"
#include "tusb.h"
#include "tusb_config.h"

//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTYPES
//--------------------------------------------------------------------+

#ifndef AUDIO_SAMPLE_RATE
#define AUDIO_SAMPLE_RATE 48000
#endif
#define AUDIO_SAMPLE_RATE CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE

/* Blink pattern
* - 250 ms : device not mounted
Expand All @@ -70,7 +69,7 @@ uint8_t clkValid;
audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; // Volume range state
audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state

// Audio test data
// Audio test data, each buffer contains 2 channels, buffer[0] for CH0-1, buffer[1] for CH1-2
uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ/2]; // Ensure half word aligned

void led_blinking_task(void);
Expand All @@ -97,6 +96,27 @@ int main(void)
sampleFreqRng.subrange[0].bMax = AUDIO_SAMPLE_RATE;
sampleFreqRng.subrange[0].bRes = 0;

// Generate dummy data
uint16_t * p_buff = i2s_dummy_buffer[0];
uint16_t dataVal = 1;
for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++)
{
// CH0 saw wave
*p_buff++ = dataVal;
// CH1 inverted saw wave
*p_buff++ = 60 + AUDIO_SAMPLE_RATE/1000 - dataVal;
dataVal++;
}
p_buff = i2s_dummy_buffer[1];
for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++)
{
// CH3 square wave
*p_buff++ = cnt < (AUDIO_SAMPLE_RATE/1000/2) ? 120:170;
// CH4 sinus wave
float t = 2*3.1415f * cnt / (AUDIO_SAMPLE_RATE/1000);
*p_buff++ = (uint16_t)(sinf(t) * 25) + 200;
}

while (1)
{
tud_task(); // tinyusb device task
Expand Down Expand Up @@ -400,7 +420,17 @@ bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, u
(void) ep_in;
(void) cur_alt_setting;

for (uint8_t cnt=0; cnt < CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; cnt++)

// In read world application data flow is driven by I2S clock,
// both tud_audio_tx_done_pre_load_cb() & tud_audio_tx_done_post_load_cb() are hardly used.
// For example in your I2S receive callback:
// void I2S_Rx_Callback(int channel, const void* data, uint16_t samples)
// {
// tud_audio_write_support_ff(channel, data, samples * N_BYTES_PER_SAMPLE * N_CHANNEL_PER_FIFO);
// }

// Write I2S buffer into FIFO
for (uint8_t cnt=0; cnt < 2; cnt++)
{
tud_audio_write_support_ff(cnt, i2s_dummy_buffer[cnt], AUDIO_SAMPLE_RATE/1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX);
}
Expand All @@ -416,22 +446,6 @@ bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uin
(void) ep_in;
(void) cur_alt_setting;

uint16_t dataVal;

// Generate dummy data
for (uint16_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; cnt++)
{
uint16_t * p_buff = i2s_dummy_buffer[cnt]; // 2 bytes per sample
dataVal = 1;
for (uint16_t cnt2 = 0; cnt2 < AUDIO_SAMPLE_RATE/1000; cnt2++)
{
for (uint8_t cnt3 = 0; cnt3 < CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX; cnt3++)
{
*p_buff++ = dataVal;
}
dataVal++;
}
}
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# print(sd.query_devices())

fs = 48000 # Sample rate
duration = 100e-3 # Duration of recording
duration = 20e-3 # Duration of recording

if platform.system() == 'Windows':
# WDM-KS is needed since there are more than one MicNode device APIs (at least in Windows)
Expand All @@ -25,9 +25,14 @@
sd.wait() # Wait until recording is finished
print('Done!')


time = np.arange(0, duration, 1 / fs) # time vector
# strip starting zero
myrecording = myrecording[100:]
time = time[100:]
plt.plot(time, myrecording)
plt.xlabel('Time [s]')
plt.ylabel('Amplitude')
plt.title('MicNode 4 Channel')
plt.legend(['CH-1', 'CH-2', 'CH-3','CH-4'])
plt.show()
3 changes: 2 additions & 1 deletion examples/device/audio_4_channel_mic/src/tusb_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ extern "C" {
//--------------------------------------------------------------------

// Have a look into audio_device.h for all configurations
#define CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE 48000

#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_MIC_FOUR_CH_DESC_LEN

Expand All @@ -112,7 +113,7 @@ extern "C" {
#define CFG_TUD_AUDIO_ENABLE_EP_IN 1
#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup
#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 4 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup
#define CFG_TUD_AUDIO_EP_SZ_IN (48 + 1) * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX // 48 Samples (48 kHz) x 2 Bytes/Sample x CFG_TUD_AUDIO_N_CHANNELS_TX Channels - the Windows driver always needs an extra sample per channel of space more, otherwise it complains... found by trial and error
#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX)
#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN
#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN

Expand Down
Loading

1 comment on commit 118823c

@Protoxy22
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool

Please sign in to comment.