60fps Limit + GENERAL_DEFAULT_WIRED_MODE can be set in sdkconfig

This commit is contained in:
PhosphorosVR
2025-08-26 01:39:40 +02:00
parent 06394f9654
commit cb569c9e47
12 changed files with 108 additions and 57 deletions

View File

@@ -1,6 +1,6 @@
// source: https://github.com/espressif/esp-iot-solution/blob/4730d91db70df7e6e0a3191d725ab1c5f98ff9ce/examples/usb/device/usb_webcam/bootloader_components/boot_hooks/boot_hooks.c
#ifdef CONFIG_GENERAL_WIRED_MODE
#ifdef CONFIG_GENERAL_DEFAULT_WIRED_MODE
#include "esp_log.h"
#include "soc/rtc_cntl_struct.h"
#include "soc/usb_serial_jtag_reg.h"

View File

@@ -48,7 +48,7 @@ void CameraManager::setupCameraPinout()
ESP_LOGI(CAMERA_MANAGER_TAG, "CAM_BOARD");
#endif
#if CONFIG_GENERAL_WIRED_MODE
#if CONFIG_GENERAL_DEFAULT_WIRED_MODE
xclk_freq_hz = CONFIG_CAMERA_USB_XCLK_FREQ;
#endif
@@ -82,7 +82,7 @@ void CameraManager::setupCameraPinout()
.jpeg_quality = 7, // 0-63, for OV series camera sensors, lower number means higher quality // Below 6 stability problems
.fb_count = 2, // When jpeg mode is used, if fb_count more than one, the driver will work in continuous mode.
.fb_location = CAMERA_FB_IN_DRAM,
.grab_mode = CAMERA_GRAB_WHEN_EMPTY,
.grab_mode = CAMERA_GRAB_LATEST, //CAMERA_GRAB_WHEN_EMPTY
};
}
@@ -196,7 +196,7 @@ bool CameraManager::setupCamera()
return false;
}
#if CONFIG_GENERAL_WIRED_MODE
#if CONFIG_GENERAL_DEFAULT_WIRED_MODE
const auto temp_sensor = esp_camera_sensor_get();
// Thanks to lick_it, we discovered that OV5640 likes to overheat when

View File

@@ -35,7 +35,17 @@ struct DeviceMode_t : BaseConfigModel
void load()
{
int stored_mode = this->pref->getInt("mode", 0);
// Default mode can be controlled via sdkconfig:
// - If CONFIG_GENERAL_DEFAULT_WIRED_MODE is enabled, default to UVC
// - Otherwise default to AUTO
int default_mode =
#if CONFIG_GENERAL_DEFAULT_WIRED_MODE
static_cast<int>(StreamingMode::UVC);
#else
static_cast<int>(StreamingMode::AUTO);
#endif
int stored_mode = this->pref->getInt("mode", default_mode);
this->mode = static_cast<StreamingMode>(stored_mode);
ESP_LOGI("DeviceMode", "Loaded device mode: %d", stored_mode);
}

View File

@@ -91,6 +91,31 @@ static uvc_fb_t *UVCStreamHelpers::camera_fb_get_cb(void *cb_ctx)
return nullptr;
}
//--------------------------------------------------------------------------------------------------------------
// Pace frames to exactly 60 fps (drop extras). Uses fixed-point accumulator
// to achieve an exact average of 60.000 fps without drifting.
static int64_t next_deadline_us = 0;
static int rem_acc = 0; // remainder accumulator for 1e6 % fps distribution
constexpr int target_fps = 60;
constexpr int64_t us_per_sec = 1000000LL;
constexpr int base_interval_us = us_per_sec / target_fps; // 16666
constexpr int rem_us = us_per_sec % target_fps; // 40
const int64_t now_us = esp_timer_get_time();
if (next_deadline_us == 0)
{
// First frame: allow immediately and schedule next slot from now
next_deadline_us = now_us;
}
if (now_us < next_deadline_us)
{
// Too early for next frame: drop this camera buffer
esp_camera_fb_return(s_fb.cam_fb_p);
s_fb.cam_fb_p = nullptr;
return nullptr;
}
//--------------------------------------------------------------------------------------------------------------
s_fb.uvc_fb.buf = s_fb.cam_fb_p->buf;
s_fb.uvc_fb.len = s_fb.cam_fb_p->len;
s_fb.uvc_fb.width = s_fb.cam_fb_p->width;
@@ -105,6 +130,20 @@ static uvc_fb_t *UVCStreamHelpers::camera_fb_get_cb(void *cb_ctx)
esp_camera_fb_return(s_fb.cam_fb_p);
return nullptr;
}
//--------------------------------------------------------------------------------------------------------------
// Schedule the next allowed frame time: base interval plus distributed remainder
rem_acc += rem_us;
int extra_us = 0;
if (rem_acc >= target_fps)
{
rem_acc -= target_fps;
extra_us = 1;
}
// Accumulate from the previous deadline to avoid drift; if we are badly late, catch up from now
const int64_t base_next = next_deadline_us + base_interval_us + extra_us;
next_deadline_us = (base_next < now_us) ? now_us : base_next;
//--------------------------------------------------------------------------------------------------------------
return &s_fb.uvc_fb;
}
@@ -119,7 +158,7 @@ static void UVCStreamHelpers::camera_fb_return_cb(uvc_fb_t *fb, void *cb_ctx)
esp_err_t UVCStreamManager::setup()
{
#ifndef CONFIG_GENERAL_WIRED_MODE
#ifndef CONFIG_GENERAL_DEFAULT_WIRED_MODE
ESP_LOGE(UVC_STREAM_TAG, "The board does not support UVC, please, setup WiFi connection.");
return ESP_FAIL;
#endif

View File

@@ -6,9 +6,13 @@ endmenu
menu "OpenIris: General Configuration"
config GENERAL_WIRED_MODE
config GENERAL_DEFAULT_WIRED_MODE
bool "Wired mode"
default false
help
Enables UVC (wired) support in the firmware. When enabled, the
default device streaming mode will be UVC unless overridden by a
saved preference. When disabled, the default mode is AUTO.
config GENERAL_UVC_DELAY
int "UVC delay (s)"

View File

@@ -22,7 +22,7 @@
#include <RestAPI.hpp>
#include <main_globals.hpp>
#ifdef CONFIG_GENERAL_WIRED_MODE
#ifdef CONFIG_GENERAL_DEFAULT_WIRED_MODE
#include <UVCStream.hpp>
#endif
@@ -49,7 +49,7 @@ StreamServer streamServer(80, stateManager);
auto *restAPI = new RestAPI("http://0.0.0.0:81", commandManager);
#ifdef CONFIG_GENERAL_WIRED_MODE
#ifdef CONFIG_GENERAL_DEFAULT_WIRED_MODE
UVCStreamManager uvcStream;
#endif
@@ -95,7 +95,7 @@ void start_video_streaming(void *arg)
if (deviceMode == StreamingMode::UVC)
{
#ifdef CONFIG_GENERAL_WIRED_MODE
#ifdef CONFIG_GENERAL_DEFAULT_WIRED_MODE
ESP_LOGI("[MAIN]", "Starting UVC streaming mode.");
ESP_LOGI("[MAIN]", "Initializing UVC hardware...");
// If we were given the Serial task handle, stop the task and uninstall the driver
@@ -120,7 +120,7 @@ void start_video_streaming(void *arg)
ESP_LOGI("[MAIN]", "UVC streaming started");
return; // UVC path complete, do not fall through to WiFi
#else
ESP_LOGE("[MAIN]", "UVC mode selected but the board likely does not support it.");
ESP_LOGE("[MAIN]", "UVC mode selected but the board likely does not support it.");
ESP_LOGI("[MAIN]", "Falling back to WiFi mode if credentials available");
deviceMode = StreamingMode::WIFI;
#endif
@@ -207,12 +207,12 @@ void startup_timer_callback(void *arg)
}
else if (deviceMode == StreamingMode::UVC)
{
#ifdef CONFIG_GENERAL_WIRED_MODE
#ifdef CONFIG_GENERAL_DEFAULT_WIRED_MODE
ESP_LOGI("[MAIN]", "Starting UVC streaming automatically");
activate_streaming(serialTaskHandle);
#else
ESP_LOGE("[MAIN]", "UVC mode selected but CONFIG_GENERAL_WIRED_MODE not enabled in build!");
ESP_LOGI("[MAIN]", "Device will stay in setup mode. Enable CONFIG_GENERAL_WIRED_MODE and rebuild.");
ESP_LOGE("[MAIN]", "UVC mode selected but CONFIG_GENERAL_DEFAULT_WIRED_MODE not enabled in build!");
ESP_LOGI("[MAIN]", "Device will stay in setup mode. Enable CONFIG_GENERAL_DEFAULT_WIRED_MODE and rebuild.");
#endif
}
else

View File

@@ -514,9 +514,9 @@ CONFIG_BOOT_ROM_LOG_ALWAYS_ON=y
# CONFIG_ESPTOOLPY_NO_STUB is not set
# CONFIG_ESPTOOLPY_OCT_FLASH is not set
CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT=y
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set
# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set
# CONFIG_ESPTOOLPY_FLASHMODE_DIO is not set
CONFIG_ESPTOOLPY_FLASHMODE_DIO=y
# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set
CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR=y
CONFIG_ESPTOOLPY_FLASHMODE="dio"
@@ -527,13 +527,13 @@ CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_ESPTOOLPY_FLASHFREQ="80m"
# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set
# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set
# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set
# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set
# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set
# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set
CONFIG_ESPTOOLPY_FLASHSIZE="4MB"
CONFIG_ESPTOOLPY_FLASHSIZE="8MB"
# CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE is not set
CONFIG_ESPTOOLPY_BEFORE_RESET=y
# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set
@@ -570,7 +570,7 @@ CONFIG_ENV_GPIO_OUT_RANGE_MAX=48
#
# OpenIris: General Configuration
#
CONFIG_GENERAL_WIRED_MODE=y
# CONFIG_GENERAL_DEFAULT_WIRED_MODE is not set
CONFIG_GENERAL_UVC_DELAY=30
# end of OpenIris: General Configuration
@@ -595,32 +595,32 @@ CONFIG_WIFI_AP_PASSWORD="12345678"
# OpenIris: LED Configuration
#
CONFIG_LED_BLINK_GPIO=8
CONFIG_LED_EXTERNAL_GPIO=1
CONFIG_LED_EXTERNAL_GPIO=9
CONFIG_LED_EXTERNAL_CONTROL=y
CONFIG_LED_EXTERNAL_PWM_FREQ=5000
CONFIG_LED_EXTERNAL_PWM_FREQ=20000
CONFIG_LED_EXTERNAL_PWM_DUTY_CYCLE=100
# end of OpenIris: LED Configuration
#
# Camera sensor pinout configuration
#
CONFIG_CAMERA_MODULE_NAME="SWROOM_BABBLE_S3"
CONFIG_CAMERA_MODULE_NAME="FaceFocusVR_Face"
CONFIG_PWDN_GPIO_NUM=-1
CONFIG_RESET_GPIO_NUM=-1
CONFIG_XCLK_GPIO_NUM=4
CONFIG_SIOD_GPIO_NUM=48
CONFIG_SIOC_GPIO_NUM=47
CONFIG_Y9_GPIO_NUM=13
CONFIG_Y8_GPIO_NUM=5
CONFIG_Y7_GPIO_NUM=6
CONFIG_Y6_GPIO_NUM=15
CONFIG_Y5_GPIO_NUM=17
CONFIG_Y4_GPIO_NUM=8
CONFIG_Y3_GPIO_NUM=18
CONFIG_Y2_GPIO_NUM=16
CONFIG_VSYNC_GPIO_NUM=21
CONFIG_HREF_GPIO_NUM=14
CONFIG_PCLK_GPIO_NUM=7
CONFIG_XCLK_GPIO_NUM=10
CONFIG_SIOD_GPIO_NUM=40
CONFIG_SIOC_GPIO_NUM=39
CONFIG_Y9_GPIO_NUM=48
CONFIG_Y8_GPIO_NUM=11
CONFIG_Y7_GPIO_NUM=12
CONFIG_Y6_GPIO_NUM=14
CONFIG_Y5_GPIO_NUM=16
CONFIG_Y4_GPIO_NUM=18
CONFIG_Y3_GPIO_NUM=17
CONFIG_Y2_GPIO_NUM=15
CONFIG_VSYNC_GPIO_NUM=38
CONFIG_HREF_GPIO_NUM=47
CONFIG_PCLK_GPIO_NUM=13
# end of Camera sensor pinout configuration
#
@@ -1155,21 +1155,19 @@ CONFIG_SPIRAM=y
#
# SPI RAM config
#
CONFIG_SPIRAM_MODE_QUAD=y
# CONFIG_SPIRAM_MODE_OCT is not set
# CONFIG_SPIRAM_MODE_QUAD is not set
CONFIG_SPIRAM_MODE_OCT=y
CONFIG_SPIRAM_TYPE_AUTO=y
# CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set
# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set
# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set
CONFIG_SPIRAM_CLK_IO=30
CONFIG_SPIRAM_CS_IO=26
# CONFIG_SPIRAM_XIP_FROM_PSRAM is not set
# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set
# CONFIG_SPIRAM_RODATA is not set
# CONFIG_SPIRAM_SPEED_120M is not set
CONFIG_SPIRAM_SPEED_80M=y
# CONFIG_SPIRAM_SPEED_40M is not set
CONFIG_SPIRAM_SPEED=80
# CONFIG_SPIRAM_ECC_ENABLE is not set
CONFIG_SPIRAM_BOOT_INIT=y
CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION=y
# CONFIG_SPIRAM_IGNORE_NOTFOUND is not set
@@ -2242,7 +2240,7 @@ CONFIG_FRAMESIZE_QVGA=y
# CONFIG_FRAMESIZE_SVGA is not set
# CONFIG_FRAMESIZE_HD is not set
# CONFIG_FRAMESIZE_FHD is not set
CONFIG_UVC_CAM1_FRAMERATE=90
CONFIG_UVC_CAM1_FRAMERATE=60
CONFIG_UVC_CAM1_FRAMESIZE_WIDTH=240
CONFIG_UVC_CAM1_FRAMESIZE_HEIGT=240
CONFIG_UVC_CAM1_MULTI_FRAMESIZE=y
@@ -2257,7 +2255,7 @@ CONFIG_UVC_CAM1_MULTI_FRAMESIZE=y
#
CONFIG_UVC_MULTI_FRAME_WIDTH_1=240
CONFIG_UVC_MULTI_FRAME_HEIGHT_1=240
CONFIG_UVC_MULTI_FRAME_FPS_1=90
CONFIG_UVC_MULTI_FRAME_FPS_1=60
# end of FRAME_SIZE_1
#
@@ -2265,7 +2263,7 @@ CONFIG_UVC_MULTI_FRAME_FPS_1=90
#
CONFIG_UVC_MULTI_FRAME_WIDTH_2=240
CONFIG_UVC_MULTI_FRAME_HEIGHT_2=240
CONFIG_UVC_MULTI_FRAME_FPS_2=90
CONFIG_UVC_MULTI_FRAME_FPS_2=60
# end of FRAME_SIZE_2
#
@@ -2273,7 +2271,7 @@ CONFIG_UVC_MULTI_FRAME_FPS_2=90
#
CONFIG_UVC_MULTI_FRAME_WIDTH_3=240
CONFIG_UVC_MULTI_FRAME_HEIGHT_3=240
CONFIG_UVC_MULTI_FRAME_FPS_3=90
CONFIG_UVC_MULTI_FRAME_FPS_3=60
# end of FRAME_SIZE_3
# end of UVC_MULTI_FRAME_CONFIG
@@ -2386,9 +2384,9 @@ CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y
CONFIG_LOG_BOOTLOADER_LEVEL=3
# CONFIG_APP_ROLLBACK_ENABLE is not set
# CONFIG_FLASH_ENCRYPTION_ENABLED is not set
CONFIG_FLASHMODE_QIO=y
# CONFIG_FLASHMODE_QIO is not set
# CONFIG_FLASHMODE_QOUT is not set
# CONFIG_FLASHMODE_DIO is not set
CONFIG_FLASHMODE_DIO=y
# CONFIG_FLASHMODE_DOUT is not set
CONFIG_MONITOR_BAUD=115200
# CONFIG_OPTIMIZATION_LEVEL_DEBUG is not set

View File

@@ -570,7 +570,7 @@ CONFIG_ENV_GPIO_OUT_RANGE_MAX=48
#
# OpenIris: General Configuration
#
# CONFIG_GENERAL_WIRED_MODE is not set
# CONFIG_GENERAL_DEFAULT_WIRED_MODE is not set
# CONFIG_GENERAL_UVC_DELAY is not set
# end of OpenIris: General Configuration
@@ -2242,7 +2242,7 @@ CONFIG_FRAMESIZE_QVGA=y
# CONFIG_FRAMESIZE_SVGA is not set
# CONFIG_FRAMESIZE_HD is not set
# CONFIG_FRAMESIZE_FHD is not set
CONFIG_UVC_CAM1_FRAMERATE=90
CONFIG_UVC_CAM1_FRAMERATE=60
CONFIG_UVC_CAM1_FRAMESIZE_WIDTH=240
CONFIG_UVC_CAM1_FRAMESIZE_HEIGT=240
CONFIG_UVC_CAM1_MULTI_FRAMESIZE=y
@@ -2257,7 +2257,7 @@ CONFIG_UVC_CAM1_MULTI_FRAMESIZE=y
#
CONFIG_UVC_MULTI_FRAME_WIDTH_1=240
CONFIG_UVC_MULTI_FRAME_HEIGHT_1=240
CONFIG_UVC_MULTI_FRAME_FPS_1=90
CONFIG_UVC_MULTI_FRAME_FPS_1=60
# end of FRAME_SIZE_1
#
@@ -2265,7 +2265,7 @@ CONFIG_UVC_MULTI_FRAME_FPS_1=90
#
CONFIG_UVC_MULTI_FRAME_WIDTH_2=240
CONFIG_UVC_MULTI_FRAME_HEIGHT_2=240
CONFIG_UVC_MULTI_FRAME_FPS_2=90
CONFIG_UVC_MULTI_FRAME_FPS_2=60
# end of FRAME_SIZE_2
#
@@ -2273,7 +2273,7 @@ CONFIG_UVC_MULTI_FRAME_FPS_2=90
#
CONFIG_UVC_MULTI_FRAME_WIDTH_3=240
CONFIG_UVC_MULTI_FRAME_HEIGHT_3=240
CONFIG_UVC_MULTI_FRAME_FPS_3=90
CONFIG_UVC_MULTI_FRAME_FPS_3=60
# end of FRAME_SIZE_3
# end of UVC_MULTI_FRAME_CONFIG

View File

@@ -59,4 +59,4 @@ CONFIG_LED_EXTERNAL_GPIO=9
CONFIG_LED_EXTERNAL_PWM_FREQ=20000
CONFIG_LED_EXTERNAL_PWM_DUTY_CYCLE=50
CONFIG_CAMERA_USB_XCLK_FREQ=23000000
CONFIG_GENERAL_WIRED_MODE=y
CONFIG_GENERAL_DEFAULT_WIRED_MODE=y

View File

@@ -59,4 +59,4 @@ CONFIG_LED_EXTERNAL_GPIO=9
CONFIG_LED_EXTERNAL_PWM_FREQ=20000
CONFIG_LED_EXTERNAL_PWM_DUTY_CYCLE=100
CONFIG_CAMERA_USB_XCLK_FREQ=23000000
CONFIG_GENERAL_WIRED_MODE=y
CONFIG_GENERAL_DEFAULT_WIRED_MODE=y

View File

@@ -51,4 +51,4 @@ CONFIG_LED_EXTERNAL_PWM_FREQ=5000
CONFIG_LED_EXTERNAL_PWM_DUTY_CYCLE=100
CONFIG_LED_EXTERNAL_GPIO=1
CONFIG_CAMERA_USB_XCLK_FREQ=23000000
CONFIG_GENERAL_WIRED_MODE=y
# CONFIG_GENERAL_DEFAULT_WIRED_MODE is not set

View File

@@ -56,4 +56,4 @@ CONFIG_SPIRAM_SPEED=80
CONFIG_SPIRAM_SPEED_80M=y
# CONFIG_LED_EXTERNAL_CONTROL is not set
CONFIG_CAMERA_USB_XCLK_FREQ=23000000
CONFIG_GENERAL_WIRED_MODE=y
# CONFIG_GENERAL_DEFAULT_WIRED_MODE is not set