Merge branch 'examples/mp3_demo_support_usb_headset' into 'master'

feat: mp3 demo support usb headset

Closes BOX-127

See merge request ae_group/esp-box!111
This commit is contained in:
Li Bo
2024-07-12 08:57:16 +08:00
12 changed files with 425 additions and 33 deletions
+18 -2
View File
@@ -6,7 +6,16 @@
| ESP32-S3-BOX-Lite | YES |
| ESP32-S3-BOX-3 | YES |
Play MP3 music on ESP-BOX.
Playing MP3 music on the ESP-BOX supports external USB headphone playback (only compatible with **ESP32-S3-BOX-3**) and playback through the built-in speakers of the ESP-BOX.
When USB headphones are connected, the example defaults to playing through the USB headphones. When the headphones are disconnected, it automatically switches to speaker playback. When the headphones are reconnected, it switches back to headphone playback.
> **Note:** Playing music through USB headphones requires the USB port to **support power output**. However, the USB Type-C port on the left side of the ESP-BOX does not provide power output. Therefore, You need to connect it to the **ESP32-S3-BOX-3-DOCK** base and use a **USB-A to Type-C adapter** (or a **USB-A to 3.5mm headphone jack adapter**) for operation, as shown in the diagram below.
<div align="center">
<img src="https://dl.espressif.com/ae/esp-box/box_mp3_demo.png/box_mp3_demo.png" width="60%">
</div>
This demo will scan the files in the specified directory (`/spiffs` by default) and try to decode and play. You can manually mount the SD card and switch to play MP3 files from the SD card.
@@ -16,8 +25,10 @@ We will support switching the sample rate and the number of channels in the next
### Hardware Required
* A ESP32-S3-Box or ESP32-S3-BOX-Lite
* A ESP32-S3-BOX-3 / ESP32-S3-Box / ESP32-S3-BOX-Lite
* A USB-C cable for power supply and programming
* ESP32-S3-BOX-3-DOCK
* a USB headphones or USB-A to 3.5-mm headphone jack adapter
Follow detailed instructions provided specifically for this example.
@@ -29,3 +40,8 @@ Once a complete flash process has been performed, you can use `idf.py app-flash
(To exit the serial monitor, type `Ctrl-]`. Please reset the development board f you cannot exit the monitor.)
### Demo Display
<div align="center">
<img src="https://dl.espressif.com/ae/esp-box/box_mp3_demo.gif/box_mp3_demo.gif" width="60%">
</div>
+3 -2
View File
@@ -2,5 +2,6 @@
dependencies:
idf: ">=5.0"
chmorgan/esp-audio-player: "1.0.5"
chmorgan/esp-file-iterator: "1.0.0"
chmorgan/esp-audio-player: "1.0.*"
chmorgan/esp-file-iterator: "1.0.0"
usb_host_uac: "1.0.*"
+7 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
@@ -24,6 +24,12 @@ void ui_audio_start(file_iterator_instance_t *i);
*/
uint8_t get_sys_volume();
/**
* @brief get current music index
*
*/
uint8_t get_current_music_index();
#ifdef __cplusplus
}
#endif
+338 -16
View File
@@ -11,25 +11,334 @@
#include "file_iterator.h"
#include "ui_audio.h"
#include "bsp_board.h"
#include "esp_spiffs.h"
#include "usb/usb_host.h"
#include "usb/uac_host.h"
#include "audio_player.h"
#include "file_iterator.h"
#include "mp3_demo.h"
static esp_err_t audio_mute_function(AUDIO_PLAYER_MUTE_SETTING setting)
static const char *TAG = "mp3_demo";
#define USB_HOST_TASK_PRIORITY 5
#define UAC_TASK_PRIORITY 5
#define USER_TASK_PRIORITY 2
#define SPIFFS_BASE "/spiffs"
#define MP3_FILE_NAME "/For_Elise.mp3"
#define DEFAULT_VOLUME 60
static audio_player_t audio_player_type = AUDIO_PLAYER_I2S;
static QueueHandle_t s_event_queue = NULL;
static uac_host_device_handle_t s_audio_player_handle = NULL;
static audio_player_config_t player_config = {0};
static FILE *s_fp = NULL;
static void uac_device_callback(uac_host_device_handle_t uac_device_handle, const uac_host_device_event_t event, void *arg);
static file_iterator_instance_t *file_iterator = NULL;
/**
* @brief event group
*
* APP_EVENT - General control event
* UAC_DRIVER_EVENT - UAC Host Driver event, such as device connection
* UAC_DEVICE_EVENT - UAC Host Device event, such as rx/tx completion, device disconnection
*/
typedef enum {
APP_EVENT = 0,
UAC_DRIVER_EVENT,
UAC_DEVICE_EVENT,
} event_group_t;
typedef struct {
event_group_t event_group;
union {
struct {
uint8_t addr;
uint8_t iface_num;
uac_host_driver_event_t event;
void *arg;
} driver_evt;
struct {
uac_host_device_handle_t handle;
uac_host_driver_event_t event;
void *arg;
} device_evt;
};
} s_event_queue_t;
static esp_err_t _audio_player_mute_fn(AUDIO_PLAYER_MUTE_SETTING setting)
{
// Volume saved when muting and restored when unmuting. Restoring volume is necessary
// as es8311_set_voice_mute(true) results in voice volume (REG32) being set to zero.
uint8_t volume = get_sys_volume();
esp_err_t ret = ESP_OK;
if (audio_player_type == AUDIO_PLAYER_I2S) {
// Volume saved when muting and restored when unmuting. Restoring volume is necessary
// as es8311_set_voice_mute(true) results in voice volume (REG32) being set to zero.
uint8_t volume = get_sys_volume();
bsp_codec_mute_set(setting == AUDIO_PLAYER_MUTE ? true : false);
bsp_codec_mute_set(setting == AUDIO_PLAYER_MUTE ? true : false);
// restore the voice volume upon unmuting
if (setting == AUDIO_PLAYER_UNMUTE) {
bsp_codec_volume_set(volume, NULL);
// restore the voice volume upon unmuting
if (setting == AUDIO_PLAYER_UNMUTE) {
bsp_codec_volume_set(volume, NULL);
}
ret = ESP_OK;
} else {
if (s_audio_player_handle == NULL) {
return ESP_ERR_INVALID_STATE;
}
ESP_LOGI(TAG, "mute setting: %s", setting == 0 ? "mute" : "unmute");
ret = uac_host_device_set_mute(s_audio_player_handle, (setting == 0 ? true : false));
}
return ret;
}
static esp_err_t _audio_player_write_fn(void *audio_buffer, size_t len, size_t *bytes_written, uint32_t timeout_ms)
{
esp_err_t ret = ESP_OK;
if (audio_player_type == AUDIO_PLAYER_I2S) {
ret = bsp_i2s_write(audio_buffer, len, bytes_written, timeout_ms);
} else {
if (s_audio_player_handle == NULL) {
return ESP_ERR_INVALID_STATE;
}
*bytes_written = 0;
esp_err_t ret = uac_host_device_write(s_audio_player_handle, audio_buffer, len, timeout_ms);
if (ret == ESP_OK) {
*bytes_written = len;
}
}
return ESP_OK;
return ret;
}
static esp_err_t _audio_player_std_clock(uint32_t rate, uint32_t bits_cfg, i2s_slot_mode_t ch)
{
esp_err_t ret = ESP_OK;
if (audio_player_type == AUDIO_PLAYER_I2S) {
ret = bsp_codec_set_fs(rate, bits_cfg, ch);
} else {
if (s_audio_player_handle == NULL) {
return ESP_ERR_INVALID_STATE;
}
ESP_LOGI(TAG, "Re-config: speaker rate %"PRIu32", bits %"PRIu32", mode %s", rate, bits_cfg, ch == 1 ? "MONO" : (ch == 2 ? "STEREO" : "INVALID"));
ESP_ERROR_CHECK(uac_host_device_stop(s_audio_player_handle));
const uac_host_stream_config_t stm_config = {
.channels = ch,
.bit_resolution = bits_cfg,
.sample_freq = rate,
};
ret = uac_host_device_start(s_audio_player_handle, &stm_config);
}
return ret;
}
static void _audio_player_callback(audio_player_cb_ctx_t *ctx)
{
ESP_LOGI(TAG, "ctx->audio_event = %d", ctx->audio_event);
switch (ctx->audio_event) {
case AUDIO_PLAYER_CALLBACK_EVENT_IDLE: {
ESP_LOGI(TAG, "AUDIO_PLAYER_REQUEST_IDLE");
if (s_audio_player_handle == NULL) {
break;
}
ESP_ERROR_CHECK(uac_host_device_suspend(s_audio_player_handle));
ESP_LOGI(TAG, "Play in loop");
s_fp = fopen(SPIFFS_BASE MP3_FILE_NAME, "rb");
if (s_fp) {
ESP_LOGI(TAG, "Playing '%s'", MP3_FILE_NAME);
audio_player_play(s_fp);
} else {
ESP_LOGE(TAG, "unable to open filename '%s'", MP3_FILE_NAME);
}
break;
}
case AUDIO_PLAYER_CALLBACK_EVENT_PLAYING:
ESP_LOGI(TAG, "AUDIO_PLAYER_REQUEST_PLAY");
if (s_audio_player_handle == NULL) {
break;
}
ESP_ERROR_CHECK(uac_host_device_resume(s_audio_player_handle));
uac_host_device_set_volume(s_audio_player_handle, get_sys_volume());
break;
case AUDIO_PLAYER_CALLBACK_EVENT_PAUSE:
ESP_LOGI(TAG, "AUDIO_PLAYER_REQUEST_PAUSE");
break;
default:
break;
}
}
static void uac_device_callback(uac_host_device_handle_t uac_device_handle, const uac_host_device_event_t event, void *arg)
{
if (event == UAC_HOST_DRIVER_EVENT_DISCONNECTED) {
audio_player_type = AUDIO_PLAYER_I2S;
// stop audio player first
s_audio_player_handle = NULL;
// audio_player_stop();
ESP_LOGI(TAG, "UAC Device disconnected");
ESP_ERROR_CHECK(uac_host_device_close(uac_device_handle));
return;
}
// Send uac device event to the event queue
s_event_queue_t evt_queue = {
.event_group = UAC_DEVICE_EVENT,
.device_evt.handle = uac_device_handle,
.device_evt.event = event,
.device_evt.arg = arg
};
// should not block here
xQueueSend(s_event_queue, &evt_queue, 0);
}
static void uac_host_lib_callback(uint8_t addr, uint8_t iface_num, const uac_host_driver_event_t event, void *arg)
{
// Send uac driver event to the event queue
s_event_queue_t evt_queue = {
.event_group = UAC_DRIVER_EVENT,
.driver_evt.addr = addr,
.driver_evt.iface_num = iface_num,
.driver_evt.event = event,
.driver_evt.arg = arg
};
xQueueSend(s_event_queue, &evt_queue, 0);
}
/**
* @brief Start USB Host install and handle common USB host library events while app pin not low
*
* @param[in] arg Not used
*/
static void usb_lib_task(void *arg)
{
const usb_host_config_t host_config = {
.skip_phy_setup = false,
.intr_flags = ESP_INTR_FLAG_LEVEL2,
};
ESP_ERROR_CHECK(usb_host_install(&host_config));
ESP_LOGI(TAG, "USB Host installed");
xTaskNotifyGive(arg);
while (true) {
uint32_t event_flags;
usb_host_lib_handle_events(portMAX_DELAY, &event_flags);
// In this example, there is only one client registered
// So, once we deregister the client, this call must succeed with ESP_OK
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) {
ESP_ERROR_CHECK(usb_host_device_free_all());
break;
}
}
ESP_LOGI(TAG, "USB Host shutdown");
// Clean up USB Host
vTaskDelay(10); // Short delay to allow clients clean-up
ESP_ERROR_CHECK(usb_host_uninstall());
vTaskDelete(NULL);
}
static void uac_lib_task(void *arg)
{
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
uac_host_driver_config_t uac_config = {
.create_background_task = true,
.task_priority = UAC_TASK_PRIORITY,
.stack_size = 4096,
.core_id = 0,
.callback = uac_host_lib_callback,
.callback_arg = NULL
};
ESP_ERROR_CHECK(uac_host_install(&uac_config));
ESP_LOGI(TAG, "UAC Class Driver installed");
s_event_queue_t evt_queue = {0};
while (1) {
if (xQueueReceive(s_event_queue, &evt_queue, pdMS_TO_TICKS(100))) {
if (UAC_DRIVER_EVENT == evt_queue.event_group) {
uac_host_driver_event_t event = evt_queue.driver_evt.event;
uint8_t addr = evt_queue.driver_evt.addr;
uint8_t iface_num = evt_queue.driver_evt.iface_num;
switch (event) {
case UAC_HOST_DRIVER_EVENT_TX_CONNECTED: {
audio_player_type = AUDIO_PLAYER_USB;
uac_host_dev_info_t dev_info;
uac_host_device_handle_t uac_device_handle = NULL;
const uac_host_device_config_t dev_config = {
.addr = addr,
.iface_num = iface_num,
.buffer_size = 16000,
.buffer_threshold = 4000,
.callback = uac_device_callback,
.callback_arg = NULL,
};
ESP_ERROR_CHECK(uac_host_device_open(&dev_config, &uac_device_handle));
ESP_ERROR_CHECK(uac_host_get_device_info(uac_device_handle, &dev_info));
ESP_LOGI(TAG, "UAC Device connected: SPK");
uac_host_printf_device_param(uac_device_handle);
const uac_host_stream_config_t stm_config = {
.channels = 2,
.bit_resolution = 16,
.sample_freq = 48000,
};
ESP_ERROR_CHECK(uac_host_device_start(uac_device_handle, &stm_config));
s_audio_player_handle = uac_device_handle;
uac_host_device_set_volume(s_audio_player_handle, get_sys_volume());
s_fp = fopen(SPIFFS_BASE MP3_FILE_NAME, "rb");
if (s_fp) {
ESP_LOGI(TAG, "Playing '%s'", MP3_FILE_NAME);
audio_player_play(s_fp);
} else {
ESP_LOGE(TAG, "unable to open filename '%s'", MP3_FILE_NAME);
}
break;
}
case UAC_HOST_DRIVER_EVENT_RX_CONNECTED: {
// we don't support MIC in this example
ESP_LOGI(TAG, "UAC Device connected: MIC");
break;
}
default:
break;
}
} else if (UAC_DEVICE_EVENT == evt_queue.event_group) {
uac_host_device_event_t event = evt_queue.device_evt.event;
switch (event) {
case UAC_HOST_DRIVER_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "UAC Device disconnected");
break;
case UAC_HOST_DEVICE_EVENT_RX_DONE:
break;
case UAC_HOST_DEVICE_EVENT_TX_DONE:
break;
case UAC_HOST_DEVICE_EVENT_TRANSFER_ERROR:
break;
default:
break;
}
} else if (APP_EVENT == evt_queue.event_group) {
break;
}
}
}
ESP_LOGI(TAG, "UAC Driver uninstall");
ESP_ERROR_CHECK(uac_host_uninstall());
}
audio_player_t get_audio_player_type(void)
{
return audio_player_type;
}
uac_host_device_handle_t get_audio_player_handle(void)
{
return s_audio_player_handle;
}
void app_main(void)
{
s_event_queue = xQueueCreate(10, sizeof(s_event_queue_t));
assert(s_event_queue != NULL);
/* Initialize I2C (for touch and audio) */
bsp_i2c_init();
@@ -49,18 +358,31 @@ void app_main(void)
bsp_spiffs_mount();
file_iterator_instance_t *file_iterator = file_iterator_new(BSP_SPIFFS_MOUNT_POINT);
file_iterator = file_iterator_new(SPIFFS_BASE);
assert(file_iterator != NULL);
/* Configure I2S peripheral and Power Amplifier */
bsp_board_init();
audio_player_config_t config = { .mute_fn = audio_mute_function,
.write_fn = bsp_i2s_write,
.clk_set_fn = bsp_codec_set_fs,
.priority = 1
};
ESP_ERROR_CHECK(audio_player_new(config));
/* Initialize audio player, the default configuration is set to play through the USB headset. */
player_config.mute_fn = _audio_player_mute_fn;
player_config.write_fn = _audio_player_write_fn;
player_config.clk_set_fn = _audio_player_std_clock;
player_config.priority = 1;
ESP_ERROR_CHECK(audio_player_new(player_config));
ESP_ERROR_CHECK(audio_player_callback_register(_audio_player_callback, NULL));
static TaskHandle_t uac_task_handle = NULL;
BaseType_t ret = xTaskCreatePinnedToCore(uac_lib_task, "uac_events", 4096, NULL,
USER_TASK_PRIORITY, &uac_task_handle, 1);
assert(ret == pdTRUE);
ret = xTaskCreatePinnedToCore(usb_lib_task, "usb_events", 4096, (void *)uac_task_handle,
USB_HOST_TASK_PRIORITY, NULL, 1);
assert(ret == pdTRUE);
bsp_display_lock(0);
ui_audio_start(file_iterator);
bsp_display_unlock();
}
+19 -2
View File
@@ -1,7 +1,7 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
* SPDX-License-Identifier: CC0-1.0
*/
#pragma once
@@ -13,6 +13,23 @@
/** Patch version number (x.x.X) */
#define MP3_DEMO_VERSION_PATCH 1
typedef enum {
AUDIO_PLAYER_I2S = 0,
AUDIO_PLAYER_USB,
} audio_player_t;
/**
* @brief get audio player type
*
*/
audio_player_t get_audio_player_type(void);
/**
* @brief get audio player handle
*
*/
uac_host_device_handle_t get_audio_player_handle(void);
/**
* Macro to convert version number into an integer
*
+32 -9
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
@@ -10,6 +10,8 @@
#include "esp_err.h"
#include "esp_log.h"
#include "bsp_board.h"
#include "usb/uac_host.h"
#include "mp3_demo.h"
static const char *TAG = "ui_audio";
@@ -32,6 +34,11 @@ uint8_t get_sys_volume()
return g_sys_volume;
}
uint8_t get_current_music_index()
{
return file_iterator_get_index(file_iterator);
}
button_style_t *ui_button_styles(void)
{
return &g_btn_styles;
@@ -132,7 +139,7 @@ void music_list_new_item_select(lv_obj_t *obj)
int item_size = file_iterator_get_count(file_iterator);
int item_index = file_iterator_get_index(file_iterator);
item_index = music_list_get_num_offset(item_index, item_size, direct);
ESP_LOGI(TAG, "slected:[%d/%d], direct:%d", item_index, item_size, direct);
ESP_LOGI(TAG, "selected:[%d/%d], direct:%d", item_index, item_size, direct);
if (1 == direct) {
file_iterator_next(file_iterator);
@@ -203,15 +210,19 @@ static void music_play_pause_cb(lv_event_t *e)
#else
static void btn_play_pause_cb(lv_event_t *event)
{
lv_obj_t *btn = (lv_obj_t *) event->target;
lv_obj_t *btn = lv_event_get_target(event);
lv_obj_t *lab = (lv_obj_t *) btn->user_data;
audio_player_state_t state = audio_player_get_state();
if (state == AUDIO_PLAYER_STATE_PAUSE) {
bsp_display_lock(0);
lv_label_set_text_static(lab, LV_SYMBOL_PAUSE);
bsp_display_unlock();
audio_player_resume();
} else if (state == AUDIO_PLAYER_STATE_PLAYING) {
bsp_display_lock(0);
lv_label_set_text_static(lab, LV_SYMBOL_PLAY);
bsp_display_unlock();
audio_player_pause();
}
}
@@ -243,9 +254,13 @@ static void btn_prev_next_cb(lv_event_t *event)
static void volume_slider_cb(lv_event_t *event)
{
lv_obj_t *slider = (lv_obj_t *) event->target;
lv_obj_t *slider = lv_event_get_target(event);
int volume = lv_slider_get_value(slider);
bsp_codec_volume_set(volume, NULL);
if (get_audio_player_type() == AUDIO_PLAYER_I2S) {
bsp_codec_volume_set(volume, NULL);
} else {
uac_host_device_set_volume(get_audio_player_handle(), volume);
}
g_sys_volume = volume;
ESP_LOGI(TAG, "volume '%d'", volume);
}
@@ -254,17 +269,23 @@ static void build_file_list(lv_obj_t *music_list)
{
lv_obj_t *label_title = (lv_obj_t *) music_list->user_data;
bsp_display_lock(0);
lv_dropdown_clear_options(music_list);
bsp_display_unlock();
size_t i = 0;
while (true) {
const char *file_name = file_iterator_get_name_from_index(file_iterator, i);
if (NULL != file_name) {
bsp_display_lock(0);
lv_dropdown_add_option(music_list, file_name, i);
bsp_display_unlock();
} else {
bsp_display_lock(0);
lv_dropdown_set_selected(music_list, 0);
lv_label_set_text_static(label_title,
file_iterator_get_name_from_index(file_iterator, 0));
bsp_display_unlock();
break;
}
i++;
@@ -288,6 +309,7 @@ static void audio_callback(audio_player_cb_ctx_t *ctx)
lv_dropdown_set_selected(music_list, index);
bsp_display_lock(0);
lv_label_set_text_static(label_title,
file_iterator_get_name_from_index(file_iterator, index));
@@ -301,11 +323,12 @@ static void audio_callback(audio_player_cb_ctx_t *ctx)
}
lv_obj_invalidate(btn_play_pause);
bsp_display_unlock();
}
static void music_list_cb(lv_event_t *event)
{
lv_obj_t *music_list = (lv_obj_t *) event->target;
lv_obj_t *music_list = lv_event_get_target(event);
if (audio_player_get_state() == AUDIO_PLAYER_STATE_PLAYING) {
uint16_t selected = lv_dropdown_get_selected(music_list);
ESP_LOGI(TAG, "switching index to '%d'", selected);
@@ -317,7 +340,7 @@ static void music_list_cb(lv_event_t *event)
void ui_audio_start(file_iterator_instance_t *i)
{
file_iterator = i;
g_sys_volume = 80;
g_sys_volume = 60;
ui_button_style_init();
@@ -435,13 +458,13 @@ void ui_audio_start(file_iterator_instance_t *i)
lv_obj_t *lab_title = lv_label_create(lv_scr_act());
lv_obj_set_user_data(lab_title, (void *) btn_play_pause);
lv_label_set_text_static(lab_title, "Scaning Files...");
lv_label_set_text_static(lab_title, "Scanning Files...");
lv_obj_set_style_text_font(lab_title, &lv_font_montserrat_32, LV_STATE_DEFAULT);
lv_obj_align(lab_title, LV_ALIGN_TOP_MID, 0, 20);
lv_obj_t *music_list = lv_dropdown_create(lv_scr_act());
lv_dropdown_clear_options(music_list);
lv_dropdown_set_options_static(music_list, "Scaning...");
lv_dropdown_set_options_static(music_list, "Scanning...");
lv_obj_set_width(music_list, 200);
lv_obj_align_to(music_list, lab_title, LV_ALIGN_OUT_BOTTOM_MID, 0, 20);
lv_obj_set_user_data(music_list, (void *) lab_title);
+8 -1
View File
@@ -29,6 +29,8 @@ CONFIG_LV_FONT_MONTSERRAT_32=y
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_FREERTOS_HZ=1000
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=4096
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=8192
CONFIG_SPIRAM_MODE_OCT=y
@@ -37,4 +39,9 @@ CONFIG_SPIRAM_SPEED_80M=y
CONFIG_SPIFFS_OBJ_NAME_LEN=128
# BSP
CONFIG_BSP_LCD_DRAW_BUF_HEIGHT=10
CONFIG_BSP_LCD_DRAW_BUF_HEIGHT=10
CONFIG_ESP_CONSOLE_UART_DEFAULT=y
CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE=2048
CONFIG_USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT=y
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.