Initial refactors to support esp32 boards

This commit is contained in:
Lorow
2025-10-30 15:06:26 +01:00
parent 3494edc822
commit 3b66642a83
38 changed files with 2901 additions and 949 deletions

View File

@@ -1,8 +1,10 @@
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
set(EXTRA_COMPONENT_DIRS ${CMAKE_CURRENT_LIST_DIR}/components)
if(IDF_TARGET STREQUAL "esp32s3" or IDF_TARGET STREQUAL "esp32s2")
list(APPEND EXTRA_COMPONENT_DIRS ${CMAKE_CURRENT_LIST_DIR}/extra_components)
endif()
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(blink)

View File

@@ -50,4 +50,10 @@ CONFIG_SPIRAM_CS_IO=26
# CONFIG_SPIRAM_RODATA is not set
# CONFIG_SPIRAM_SPEED_120M is not set
CONFIG_SPIRAM_SPEED_80M=y
# CONFIG_SUPPORTS_EXTERNAL_LED_CONTROL is not set
# CONFIG_SUPPORTS_EXTERNAL_LED_CONTROL is not set
#
# OpenIris: Serial Communication Settings
#
CONFIG_UART_PORT_NUMER=1
# end of OpenIris: Serial Communication Settings

View File

@@ -50,4 +50,10 @@ CONFIG_SPIRAM_CS_IO=26
# CONFIG_SPIRAM_RODATA is not set
# CONFIG_SPIRAM_SPEED_120M is not set
CONFIG_SPIRAM_SPEED_80M=y
# CONFIG_SUPPORTS_EXTERNAL_LED_CONTROL is not set
# CONFIG_SUPPORTS_EXTERNAL_LED_CONTROL is not set
#
# OpenIris: Serial Communication Settings
#
CONFIG_UART_PORT_NUMER=1
# end of OpenIris: Serial Communication Settings

View File

@@ -50,4 +50,10 @@ CONFIG_SPIRAM_CS_IO=26
# CONFIG_SPIRAM_RODATA is not set
# CONFIG_SPIRAM_SPEED_120M is not set
CONFIG_SPIRAM_SPEED_80M=y
# CONFIG_SUPPORTS_EXTERNAL_LED_CONTROL is not set
# CONFIG_SUPPORTS_EXTERNAL_LED_CONTROL is not set
#
# OpenIris: Serial Communication Settings
#
CONFIG_UART_PORT_NUMER=1
# end of OpenIris: Serial Communication Settings

View File

@@ -68,4 +68,10 @@ CONFIG_GENERAL_BOARD="facefocusvr_eye_l"
# CONFIG_GENERAL_ENABLE_WIRELESS is not set
# CONFIG_LED_DEBUG_ENABLE is not set
CONFIG_LED_EXTERNAL_AS_DEBUG=y
CONFIG_GENERAL_ADVERTISED_NAME="FFVR Eye L"
CONFIG_GENERAL_ADVERTISED_NAME="FFVR Eye L"
#
# OpenIris: Serial Communication Settings
#
CONFIG_UART_PORT_NUMER=1
# end of OpenIris: Serial Communication Settings

View File

@@ -68,4 +68,9 @@ CONFIG_GENERAL_BOARD="facefocusvr_eye_r"
# CONFIG_GENERAL_ENABLE_WIRELESS is not set
# CONFIG_LED_DEBUG_ENABLE is not set
CONFIG_LED_EXTERNAL_AS_DEBUG=y
CONFIG_GENERAL_ADVERTISED_NAME="FFVR Eye R"
CONFIG_GENERAL_ADVERTISED_NAME="FFVR Eye R"
#
# OpenIris: Serial Communication Settings
#
CONFIG_UART_PORT_NUMER=1
# end of OpenIris: Serial Communication Settings

View File

@@ -68,4 +68,9 @@ CONFIG_GENERAL_BOARD="facefocusvr_face"
# CONFIG_GENERAL_ENABLE_WIRELESS is not set
# CONFIG_LED_DEBUG_ENABLE is not set
CONFIG_LED_EXTERNAL_AS_DEBUG=y
CONFIG_GENERAL_ADVERTISED_NAME="FFVR Face"
CONFIG_GENERAL_ADVERTISED_NAME="FFVR Face"
#
# OpenIris: Serial Communication Settings
#
CONFIG_UART_PORT_NUMER=1
# end of OpenIris: Serial Communication Settings

View File

@@ -57,4 +57,9 @@ CONFIG_GENERAL_INCLUDE_UVC_MODE=y
# CONFIG_START_IN_UVC_MODE is not set
# CONFIG_MONITORING_LED_CURRENT is not set
CONFIG_GENERAL_BOARD="project_babble"
CONFIG_GENERAL_ENABLE_WIRELESS=y
CONFIG_GENERAL_ENABLE_WIRELESS=y
#
# OpenIris: Serial Communication Settings
#
CONFIG_UART_PORT_NUMER=1
# end of OpenIris: Serial Communication Settings

View File

@@ -2228,7 +2228,6 @@ CONFIG_TUSB_PID=0x8000
CONFIG_TUSB_MANUFACTURER="ETVR"
CONFIG_TUSB_PRODUCT="OpenIris Camera"
CONFIG_TUSB_SERIAL_NUM="12345678"
# CONFIG_UVC_SUPPORT_TWO_CAM is not set
#
# USB Cam1 Config
@@ -2567,4 +2566,9 @@ CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y
CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y
CONFIG_SUPPORT_TERMIOS=y
CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1
# End of deprecated options
# End of deprecated options
#
# OpenIris: Serial Communication Settings
#
CONFIG_UART_PORT_NUMER=1
# end of OpenIris: Serial Communication Settings

View File

@@ -62,3 +62,8 @@ CONFIG_GENERAL_INCLUDE_UVC_MODE=y
# CONFIG_MONITORING_LED_CURRENT is not set
CONFIG_GENERAL_BOARD="xiao_esp32s3"
CONFIG_GENERAL_ENABLE_WIRELESS=y
#
# OpenIris: Serial Communication Settings
#
CONFIG_UART_PORT_NUMER=1
# end of OpenIris: Serial Communication Settings

View File

@@ -49,4 +49,9 @@ CONFIG_SPIRAM_CS_IO=26
# CONFIG_SPIRAM_RODATA is not set
# CONFIG_SPIRAM_SPEED_120M is not set
CONFIG_SPIRAM_SPEED_80M=y
# CONFIG_SUPPORTS_EXTERNAL_LED_CONTROL is not set
# CONFIG_SUPPORTS_EXTERNAL_LED_CONTROL is not set
#
# OpenIris: Serial Communication Settings
#
CONFIG_UART_PORT_NUMER=1
# end of OpenIris: Serial Communication Settings

View File

@@ -49,4 +49,9 @@ CONFIG_SPIRAM_CS_IO=26
# CONFIG_SPIRAM_RODATA is not set
# CONFIG_SPIRAM_SPEED_120M is not set
CONFIG_SPIRAM_SPEED_80M=y
# CONFIG_SUPPORTS_EXTERNAL_LED_CONTROL is not set
# CONFIG_SUPPORTS_EXTERNAL_LED_CONTROL is not set
#
# OpenIris: Serial Communication Settings
#
CONFIG_UART_PORT_NUMER=1
# end of OpenIris: Serial Communication Settings

View File

@@ -49,4 +49,9 @@ CONFIG_SPIRAM_CS_IO=26
# CONFIG_SPIRAM_RODATA is not set
# CONFIG_SPIRAM_SPEED_120M is not set
CONFIG_SPIRAM_SPEED_80M=y
# CONFIG_SUPPORTS_EXTERNAL_LED_CONTROL is not set
# CONFIG_SUPPORTS_EXTERNAL_LED_CONTROL is not set
#
# OpenIris: Serial Communication Settings
#
CONFIG_UART_PORT_NUMER=1
# end of OpenIris: Serial Communication Settings

View File

@@ -1,4 +1,32 @@
idf_component_register(SRCS "SerialManager/SerialManager.cpp"
INCLUDE_DIRS "SerialManager"
REQUIRES esp_driver_uart CommandManager ProjectConfig tinyusb
set (
requires
esp_driver_uart
CommandManager
ProjectConfig
)
if ("$ENV{IDF_ETARGET}" STREQUAL "esp32s3")
list(APPEND requires
tinyusb
)
endif()
set (
source_files
"SerialManager/SerialManager.cpp"
)
if ("$ENV{IDF_ETARGET}" STREQUAL "esp32s3" OR "$ENV{IDF_ETARGET}" STREQUAL "esp32s2" )
list(APPEND source_files
"SerialManager/SerialManager_esp32s3.cpp"
)
else()
list(APPEND source_files
"SerialManager/SerialManager_esp32.cpp"
)
endif()
idf_component_register(SRCS ${source_files}
INCLUDE_DIRS "SerialManager"
REQUIRES ${requires}
)

View File

@@ -1,9 +1,6 @@
#include "SerialManager.hpp"
#include "esp_log.h"
#include "main_globals.hpp"
#include "tusb.h"
#define BUF_SIZE (1024)
SerialManager::SerialManager(std::shared_ptr<CommandManager> commandManager, esp_timer_handle_t *timerHandle)
: commandManager(commandManager), timerHandle(timerHandle)
@@ -12,62 +9,6 @@ SerialManager::SerialManager(std::shared_ptr<CommandManager> commandManager, esp
this->temp_data = static_cast<uint8_t *>(malloc(256));
}
void SerialManager::setup()
{
usb_serial_jtag_driver_config_t usb_serial_jtag_config;
usb_serial_jtag_config.rx_buffer_size = BUF_SIZE;
usb_serial_jtag_config.tx_buffer_size = BUF_SIZE;
usb_serial_jtag_driver_install(&usb_serial_jtag_config);
}
void SerialManager::try_receive()
{
static auto current_position = 0;
int len = usb_serial_jtag_read_bytes(this->temp_data, 256, 1000 / 20);
// If driver is uninstalled or an error occurs, abort read gracefully
if (len < 0)
{
return;
}
if (len > 0)
{
// Notify main that a command was received during startup
notify_startup_command_received();
}
// since we've got something on the serial port
// we gotta keep reading until we've got the whole message
// we will submit the command once we get a newline, a return or the buffer is full
for (auto i = 0; i < len; i++)
{
this->data[current_position++] = this->temp_data[i];
// if we're at the end of the buffer, try to process the command anyway
// if we've got a new line, we've finished sending the commands, process them
if (current_position >= BUF_SIZE || this->data[current_position - 1] == '\n' || this->data[current_position - 1] == '\r')
{
data[current_position] = '\0';
current_position = 0;
const nlohmann::json result = this->commandManager->executeFromJson(std::string_view(reinterpret_cast<const char *>(this->data)));
const auto resultMessage = result.dump();
usb_serial_jtag_write_bytes_chunked(resultMessage.c_str(), resultMessage.length(), 1000 / 20);
}
}
}
void SerialManager::usb_serial_jtag_write_bytes_chunked(const char *data, size_t len, size_t timeout)
{
while (len > 0)
{
auto to_write = len > BUF_SIZE ? BUF_SIZE : len;
auto written = usb_serial_jtag_write_bytes(data, to_write, timeout);
data += written;
len -= written;
}
}
// Function to notify that a command was received during startup
void SerialManager::notify_startup_command_received()
{
@@ -83,21 +24,6 @@ void SerialManager::notify_startup_command_received()
}
}
void SerialManager::shutdown()
{
// Stop heartbeats; timer will be deleted by main if needed.
// Uninstall the USB Serial JTAG driver to free the internal USB for TinyUSB.
esp_err_t err = usb_serial_jtag_driver_uninstall();
if (err == ESP_OK)
{
ESP_LOGI("[SERIAL]", "usb_serial_jtag driver uninstalled");
}
else if (err != ESP_ERR_INVALID_STATE)
{
ESP_LOGW("[SERIAL]", "usb_serial_jtag_driver_uninstall returned %s", esp_err_to_name(err));
}
}
// we can cancel this task once we're in cdc
void HandleSerialManagerTask(void *pvParameters)
{
@@ -107,72 +33,3 @@ void HandleSerialManagerTask(void *pvParameters)
serialManager->try_receive();
}
}
void HandleCDCSerialManagerTask(void *pvParameters)
{
auto const commandManager = static_cast<CommandManager *>(pvParameters);
static char buffer[BUF_SIZE];
auto idx = 0;
cdc_command_packet_t packet;
while (true)
{
if (xQueueReceive(cdcMessageQueue, &packet, portMAX_DELAY) == pdTRUE)
{
for (auto i = 0; i < packet.len; i++)
{
buffer[idx++] = packet.data[i];
// if we're at the end of the buffer, try to process the command anyway
// if we've got a new line, we've finished sending the commands, process them
if (idx >= BUF_SIZE || buffer[idx - 1] == '\n' || buffer[idx - 1] == '\r')
{
buffer[idx - 1] = '\0';
const nlohmann::json result = commandManager->executeFromJson(std::string_view(reinterpret_cast<const char *>(buffer)));
const auto resultMessage = result.dump();
tud_cdc_write(resultMessage.c_str(), resultMessage.length());
tud_cdc_write_flush();
idx = 0;
}
}
}
}
}
// tud_cdc_rx_cb is defined as TU_ATTR_WEAK so we can override it, we will be called back if we get some data
// but we don't want to do any processing here since we don't want to risk blocking
// grab the data and send it to a queue, a special task will process it and handle with the command manager
extern "C" void tud_cdc_rx_cb(uint8_t itf)
{
// we can void the interface number
(void)itf;
cdc_command_packet_t packet;
auto len = tud_cdc_available();
if (len > 0)
{
auto read = tud_cdc_read(packet.data, sizeof(packet.data));
if (read > 0)
{
// we should be safe here, given that the max buffer size is 64
packet.len = static_cast<uint8_t>(read);
xQueueSend(cdcMessageQueue, &packet, 1);
}
}
}
extern "C" void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
{
(void)itf;
(void)dtr;
(void)rts;
ESP_LOGI("[SERIAL]", "CDC line state changed: DTR=%d, RTS=%d", dtr, rts);
}
void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const *p_line_coding)
{
(void)itf;
ESP_LOGI("[SERIAL]", "CDC line coding: %" PRIu32 " bps, %d stop bits, %d parity, %d data bits",
p_line_coding->bit_rate, p_line_coding->stop_bits,
p_line_coding->parity, p_line_coding->data_bits);
}

View File

@@ -10,14 +10,15 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/uart.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include "driver/usb_serial_jtag.h"
#include "esp_vfs_usb_serial_jtag.h"
#include "esp_vfs_dev.h"
#include "esp_mac.h"
#ifndef BUF_SIZE
#define BUF_SIZE (1024)
#endif
extern "C" void tud_cdc_rx_cb(uint8_t itf);
extern "C" void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts);
@@ -39,8 +40,6 @@ public:
void shutdown();
private:
void usb_serial_jtag_write_bytes_chunked(const char *data, size_t len, size_t timeout);
std::shared_ptr<CommandManager> commandManager;
esp_timer_handle_t *timerHandle;
uint8_t *data;

View File

@@ -0,0 +1,31 @@
#include "SerialManager.hpp"
#include "esp_log.h"
#include "main_globals.hpp"
#include "driver/uart.h"
void SerialManager::setup()
{
// usb_serial_jtag_driver_config_t usb_serial_jtag_config;
// usb_serial_jtag_config.rx_buffer_size = BUF_SIZE;
// usb_serial_jtag_config.tx_buffer_size = BUF_SIZE;
// usb_serial_jtag_driver_install(&usb_serial_jtag_config);
}
void SerialManager::try_receive()
{
}
void SerialManager::shutdown()
{
// Stop heartbeats; timer will be deleted by main if needed.
// Uninstall the USB Serial JTAG driver to free the internal USB for TinyUSB.
// esp_err_t err = usb_serial_jtag_driver_uninstall();
// if (err == ESP_OK)
// {
// ESP_LOGI("[SERIAL]", "usb_serial_jtag driver uninstalled");
// }
// else if (err != ESP_ERR_INVALID_STATE)
// {
// ESP_LOGW("[SERIAL]", "usb_serial_jtag_driver_uninstall returned %s", esp_err_to_name(err));
// }
}

View File

@@ -0,0 +1,152 @@
#include "SerialManager.hpp"
#include "esp_log.h"
#include "main_globals.hpp"
#include "driver/usb_serial_jtag.h"
#include "esp_vfs_usb_serial_jtag.h"
#include "tusb.h"
void SerialManager::setup()
{
#ifndef CONFIG_USE_UART_FOR_COMMUNICATION
usb_serial_jtag_driver_config_t usb_serial_jtag_config;
usb_serial_jtag_config.rx_buffer_size = BUF_SIZE;
usb_serial_jtag_config.tx_buffer_size = BUF_SIZE;
usb_serial_jtag_driver_install(&usb_serial_jtag_config);
#endif
}
usb_serial_jtag_write_bytes_chunked(const char *data, size_t len, size_t timeout)
{
#ifndef CONFIG_USE_UART_FOR_COMMUNICATION
while (len > 0)
{
auto to_write = len > BUF_SIZE ? BUF_SIZE : len;
auto written = usb_serial_jtag_write_bytes(data, to_write, timeout);
data += written;
len -= written;
}
#endif
}
void SerialManager::try_receive()
{
static auto current_position = 0;
int len = usb_serial_jtag_read_bytes(this->temp_data, 256, 1000 / 20);
// If driver is uninstalled or an error occurs, abort read gracefully
if (len < 0)
{
return;
}
if (len > 0)
{
// Notify main that a command was received during startup
notify_startup_command_received();
}
// since we've got something on the serial port
// we gotta keep reading until we've got the whole message
// we will submit the command once we get a newline, a return or the buffer is full
for (auto i = 0; i < len; i++)
{
this->data[current_position++] = this->temp_data[i];
// if we're at the end of the buffer, try to process the command anyway
// if we've got a new line, we've finished sending the commands, process them
if (current_position >= BUF_SIZE || this->data[current_position - 1] == '\n' || this->data[current_position - 1] == '\r')
{
data[current_position] = '\0';
current_position = 0;
const nlohmann::json result = this->commandManager->executeFromJson(std::string_view(reinterpret_cast<const char *>(this->data)));
const auto resultMessage = result.dump();
usb_serial_jtag_write_bytes_chunked(resultMessage.c_str(), resultMessage.length(), 1000 / 20);
}
}
}
void SerialManager::shutdown()
{
// Uninstall the USB Serial JTAG driver to free the internal USB for TinyUSB.
esp_err_t err = usb_serial_jtag_driver_uninstall();
if (err == ESP_OK)
{
ESP_LOGI("[SERIAL]", "usb_serial_jtag driver uninstalled");
}
else if (err != ESP_ERR_INVALID_STATE)
{
ESP_LOGW("[SERIAL]", "usb_serial_jtag_driver_uninstall returned %s", esp_err_to_name(err));
}
}
void HandleCDCSerialManagerTask(void *pvParameters)
{
#ifndef CONFIG_USE_UART_FOR_COMMUNICATION
auto const commandManager = static_cast<CommandManager *>(pvParameters);
static char buffer[BUF_SIZE];
auto idx = 0;
cdc_command_packet_t packet;
while (true)
{
if (xQueueReceive(cdcMessageQueue, &packet, portMAX_DELAY) == pdTRUE)
{
for (auto i = 0; i < packet.len; i++)
{
buffer[idx++] = packet.data[i];
// if we're at the end of the buffer, try to process the command anyway
// if we've got a new line, we've finished sending the commands, process them
if (idx >= BUF_SIZE || buffer[idx - 1] == '\n' || buffer[idx - 1] == '\r')
{
buffer[idx - 1] = '\0';
const nlohmann::json result = commandManager->executeFromJson(std::string_view(reinterpret_cast<const char *>(buffer)));
const auto resultMessage = result.dump();
tud_cdc_write(resultMessage.c_str(), resultMessage.length());
tud_cdc_write_flush();
idx = 0;
}
}
}
}
#endif
}
// tud_cdc_rx_cb is defined as TU_ATTR_WEAK so we can override it, we will be called back if we get some data
// but we don't want to do any processing here since we don't want to risk blocking
// grab the data and send it to a queue, a special task will process it and handle with the command manager
extern "C" void tud_cdc_rx_cb(uint8_t itf)
{
// we can void the interface number
(void)itf;
cdc_command_packet_t packet;
auto len = tud_cdc_available();
if (len > 0)
{
auto read = tud_cdc_read(packet.data, sizeof(packet.data));
if (read > 0)
{
// we should be safe here, given that the max buffer size is 64
packet.len = static_cast<uint8_t>(read);
xQueueSend(cdcMessageQueue, &packet, 1);
}
}
}
extern "C" void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
{
(void)itf;
(void)dtr;
(void)rts;
ESP_LOGI("[SERIAL]", "CDC line state changed: DTR=%d, RTS=%d", dtr, rts);
}
void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const *p_line_coding)
{
(void)itf;
ESP_LOGI("[SERIAL]", "CDC line coding: %" PRIu32 " bps, %d stop bits, %d parity, %d data bits",
p_line_coding->bit_rate, p_line_coding->stop_bits,
p_line_coding->parity, p_line_coding->data_bits);
}

View File

@@ -1,4 +1,19 @@
set (
requires
esp_timer
esp32-camera
StateManager
CameraManager
Helpers
)
if ("$ENV{IDF_ETARGET}" STREQUAL "esp32s3")
list(APPEND required
usb_device_uvc
)
endif()
idf_component_register(SRCS "UVCStream/UVCStream.cpp"
INCLUDE_DIRS "UVCStream"
REQUIRES esp_timer esp32-camera StateManager usb_device_uvc CameraManager Helpers
REQUIRES ${requires}
)

View File

@@ -1,8 +1,9 @@
#ifdef CONFIG_GENERAL_INCLUDE_UVC_MODE
#include "UVCStream.hpp"
#include <cstdio> // for snprintf
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
// no deps on main globals here; handover is performed in main before calling setup when needed
static const char *UVC_STREAM_TAG = "[UVC DEVICE]";
@@ -94,10 +95,10 @@ static uvc_fb_t *UVCStreamHelpers::camera_fb_get_cb(void *cb_ctx)
// to the underlying camera buffer was overwritten before TinyUSB returned it.
// --- Frame pacing BEFORE grabbing a new camera frame ---
static int64_t next_deadline_us = 0; // next permitted capture time
static int rem_acc = 0; // fractional remainder accumulator
static const int target_fps = 60; // desired FPS
static const int64_t us_per_sec = 1000000; // 1e6 microseconds
static int64_t next_deadline_us = 0; // next permitted capture time
static int rem_acc = 0; // fractional remainder accumulator
static const int target_fps = 60; // desired FPS
static const int64_t us_per_sec = 1000000; // 1e6 microseconds
static const int base_interval_us = us_per_sec / target_fps; // 16666
static const int rem_us = us_per_sec % target_fps; // 40 (distributed)
@@ -167,12 +168,6 @@ static void UVCStreamHelpers::camera_fb_return_cb(uvc_fb_t *fb, void *cb_ctx)
esp_err_t UVCStreamManager::setup()
{
#ifndef CONFIG_GENERAL_INCLUDE_UVC_MODE
ESP_LOGE(UVC_STREAM_TAG, "The board does not support UVC, please, setup WiFi connection.");
return ESP_FAIL;
#endif
ESP_LOGI(UVC_STREAM_TAG, "Setting up UVC Stream");
// Allocate a fixed-size transfer buffer (compile-time constant)
uvc_buffer_size = UVCStreamManager::UVC_MAX_FRAMESIZE_SIZE;
@@ -218,4 +213,6 @@ esp_err_t UVCStreamManager::start()
ESP_LOGI(UVC_STREAM_TAG, "Starting UVC streaming");
// UVC device is already initialized in setup(), just log that we're starting
return ESP_OK;
}
}
#endif

View File

@@ -1,3 +1,4 @@
#ifdef CONFIG_GENERAL_INCLUDE_UVC_MODE
#pragma once
#ifndef UVCSTREAM_HPP
#define UVCSTREAM_HPP
@@ -33,8 +34,6 @@ extern QueueHandle_t eventQueue;
namespace UVCStreamHelpers
{
// TODO move the camera handling code to the camera manager and have the uvc manager initialize it in wired mode
typedef struct
{
camera_fb_t *cam_fb_p;
@@ -64,3 +63,4 @@ public:
};
#endif // UVCSTREAM_HPP
#endif

View File

@@ -1,76 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "sdkconfig.h"
#ifdef CONFIG_FORMAT_MJPEG_CAM1
#define FORMAT_MJPEG_CAM1 1
#endif
#ifdef CONFIG_UVC_CAM1_MULTI_FRAMESIZE
//If enable, add VGA and HVGA to list
#define UVC_CAM1_FRAME_MULTI 1
#endif
#define UVC_CAM1_FRAME_WIDTH CONFIG_UVC_CAM1_FRAMESIZE_WIDTH
#define UVC_CAM1_FRAME_HEIGHT CONFIG_UVC_CAM1_FRAMESIZE_HEIGT
#define UVC_CAM1_FRAME_RATE CONFIG_UVC_CAM1_FRAMERATE
#ifdef CONFIG_UVC_MODE_BULK_CAM1
#define UVC_CAM1_BULK_MODE
#endif
#if CONFIG_UVC_SUPPORT_TWO_CAM
#ifdef CONFIG_FORMAT_MJPEG_CAM2
#define FORMAT_MJPEG_CAM2 1
#endif
#ifdef CONFIG_UVC_CAM2_MULTI_FRAMESIZE
//If enable, add VGA and HVGA to list
#define UVC_CAM2_FRAME_MULTI 1
#endif
#define UVC_CAM2_FRAME_WIDTH CONFIG_UVC_CAM2_FRAMESIZE_WIDTH
#define UVC_CAM2_FRAME_HEIGHT CONFIG_UVC_CAM2_FRAMESIZE_HEIGT
#define UVC_CAM2_FRAME_RATE CONFIG_UVC_CAM2_FRAMERATE
#ifdef CONFIG_UVC_MODE_BULK_CAM2
#define UVC_CAM2_BULK_MODE
#endif
#endif
#ifndef UVC_CAM2_FRAME_WIDTH
#define UVC_CAM2_FRAME_WIDTH UVC_CAM1_FRAME_WIDTH
#endif
#ifndef UVC_CAM2_FRAME_HEIGHT
#define UVC_CAM2_FRAME_HEIGHT UVC_CAM1_FRAME_HEIGHT
#endif
#ifndef UVC_CAM2_FRAME_RATE
#define UVC_CAM2_FRAME_RATE UVC_CAM1_FRAME_RATE
#endif
static const struct {
int width;
int height;
int rate;
} UVC_FRAMES_INFO[][4] = {{
{UVC_CAM1_FRAME_WIDTH, UVC_CAM1_FRAME_HEIGHT, UVC_CAM1_FRAME_RATE},
{CONFIG_UVC_MULTI_FRAME_WIDTH_1, CONFIG_UVC_MULTI_FRAME_HEIGHT_1, CONFIG_UVC_MULTI_FRAME_FPS_1},
{CONFIG_UVC_MULTI_FRAME_WIDTH_2, CONFIG_UVC_MULTI_FRAME_HEIGHT_2, CONFIG_UVC_MULTI_FRAME_FPS_2},
{CONFIG_UVC_MULTI_FRAME_WIDTH_3, CONFIG_UVC_MULTI_FRAME_HEIGHT_3, CONFIG_UVC_MULTI_FRAME_FPS_3},
}, {
{UVC_CAM2_FRAME_WIDTH, UVC_CAM2_FRAME_HEIGHT, UVC_CAM2_FRAME_RATE},
{CONFIG_UVC_MULTI_FRAME_WIDTH_1, CONFIG_UVC_MULTI_FRAME_HEIGHT_1, CONFIG_UVC_MULTI_FRAME_FPS_1},
{CONFIG_UVC_MULTI_FRAME_WIDTH_2, CONFIG_UVC_MULTI_FRAME_HEIGHT_2, CONFIG_UVC_MULTI_FRAME_FPS_2},
{CONFIG_UVC_MULTI_FRAME_WIDTH_3, CONFIG_UVC_MULTI_FRAME_HEIGHT_3, CONFIG_UVC_MULTI_FRAME_FPS_3},
}
};
#define UVC_FRAME_NUM (sizeof(UVC_FRAMES_INFO[0]) / sizeof(UVC_FRAMES_INFO[0][0]))
_Static_assert(UVC_FRAME_NUM == 4, "UVC_FRAME_NUM must be 4");

View File

@@ -1,14 +1,4 @@
dependencies:
espressif/cmake_utilities:
component_hash: 05165f30922b422b4b90c08845e6d449329b97370fbd06309803d8cb539d79e3
dependencies:
- name: idf
require: private
version: '>=4.1'
source:
registry_url: https://components.espressif.com/
type: service
version: 1.1.1
espressif/esp32-camera:
component_hash: c3eb05fbeeae884a23bed9b17d48d5f0da8872beadae0c0e747d2fbea6094f06
dependencies: []
@@ -36,31 +26,15 @@ dependencies:
registry_url: https://components.espressif.com/
type: service
version: 1.8.2
espressif/tinyusb:
component_hash: 214989d502fc168241a4a4f83b097d8ac44a93cd6f1787b4ac10069a8b3bebd3
dependencies:
- name: idf
require: private
version: '>=5.0'
source:
registry_url: https://components.espressif.com/
type: service
targets:
- esp32s2
- esp32s3
- esp32p4
version: 0.15.0~10
idf:
source:
type: idf
version: 5.4.2
direct_dependencies:
- espressif/cmake_utilities
- espressif/esp32-camera
- espressif/led_strip
- espressif/mdns
- espressif/tinyusb
- idf
manifest_hash: b8a462b847225cdc561c820962ae0cb021d5ff7d688964bd6786f78b99dfa205
target: esp32s3
manifest_hash: 84f1cf4d6bb76708581c603abbe49d3a107be6979a3546c1948ed5ac48316a9b
target: esp32
version: 2.0.0

View File

@@ -0,0 +1,58 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "sdkconfig.h"
#ifdef CONFIG_FORMAT_MJPEG_CAM1
#define FORMAT_MJPEG_CAM1 1
#endif
#ifdef CONFIG_UVC_CAM1_MULTI_FRAMESIZE
// If enable, add VGA and HVGA to list
#define UVC_CAM1_FRAME_MULTI 1
#endif
#define UVC_CAM1_FRAME_WIDTH CONFIG_UVC_CAM1_FRAMESIZE_WIDTH
#define UVC_CAM1_FRAME_HEIGHT CONFIG_UVC_CAM1_FRAMESIZE_HEIGT
#define UVC_CAM1_FRAME_RATE CONFIG_UVC_CAM1_FRAMERATE
#ifdef CONFIG_UVC_MODE_BULK_CAM1
#define UVC_CAM1_BULK_MODE
#endif
#ifndef UVC_CAM2_FRAME_WIDTH
#define UVC_CAM2_FRAME_WIDTH UVC_CAM1_FRAME_WIDTH
#endif
#ifndef UVC_CAM2_FRAME_HEIGHT
#define UVC_CAM2_FRAME_HEIGHT UVC_CAM1_FRAME_HEIGHT
#endif
#ifndef UVC_CAM2_FRAME_RATE
#define UVC_CAM2_FRAME_RATE UVC_CAM1_FRAME_RATE
#endif
static const struct
{
int width;
int height;
int rate;
} UVC_FRAMES_INFO[][4] = {{
{UVC_CAM1_FRAME_WIDTH, UVC_CAM1_FRAME_HEIGHT, UVC_CAM1_FRAME_RATE},
{CONFIG_UVC_MULTI_FRAME_WIDTH_1, CONFIG_UVC_MULTI_FRAME_HEIGHT_1, CONFIG_UVC_MULTI_FRAME_FPS_1},
{CONFIG_UVC_MULTI_FRAME_WIDTH_2, CONFIG_UVC_MULTI_FRAME_HEIGHT_2, CONFIG_UVC_MULTI_FRAME_FPS_2},
{CONFIG_UVC_MULTI_FRAME_WIDTH_3, CONFIG_UVC_MULTI_FRAME_HEIGHT_3, CONFIG_UVC_MULTI_FRAME_FPS_3},
},
{
{UVC_CAM2_FRAME_WIDTH, UVC_CAM2_FRAME_HEIGHT, UVC_CAM2_FRAME_RATE},
{CONFIG_UVC_MULTI_FRAME_WIDTH_1, CONFIG_UVC_MULTI_FRAME_HEIGHT_1, CONFIG_UVC_MULTI_FRAME_FPS_1},
{CONFIG_UVC_MULTI_FRAME_WIDTH_2, CONFIG_UVC_MULTI_FRAME_HEIGHT_2, CONFIG_UVC_MULTI_FRAME_FPS_2},
{CONFIG_UVC_MULTI_FRAME_WIDTH_3, CONFIG_UVC_MULTI_FRAME_HEIGHT_3, CONFIG_UVC_MULTI_FRAME_FPS_3},
}};
#define UVC_FRAME_NUM (sizeof(UVC_FRAMES_INFO[0]) / sizeof(UVC_FRAMES_INFO[0][0]))
_Static_assert(UVC_FRAME_NUM == 4, "UVC_FRAME_NUM must be 4");

View File

@@ -20,11 +20,7 @@
static const char *TAG = "usbd_uvc";
#if CONFIG_UVC_SUPPORT_TWO_CAM
#define UVC_CAM_NUM 2
#else
#define UVC_CAM_NUM 1
#endif
typedef struct
{
@@ -85,12 +81,6 @@ void tud_suspend_cb(bool remote_wakeup_en)
{
s_uvc_device.user_config[0].stop_cb(s_uvc_device.user_config[0].cb_ctx);
}
#if CONFIG_UVC_SUPPORT_TWO_CAM
if (s_uvc_device.user_config[1].stop_cb)
{
s_uvc_device.user_config[1].stop_cb(s_uvc_device.user_config[1].cb_ctx);
}
#endif
ESP_LOGI(TAG, "Suspend");
}
@@ -178,82 +168,6 @@ static void video_task(void *arg)
}
}
#if CONFIG_UVC_SUPPORT_TWO_CAM
static void video_task2(void *arg)
{
uint32_t start_ms = 0;
uint32_t frame_num = 0;
uint32_t frame_len = 0;
uint32_t already_start = 0;
uint32_t tx_busy = 0;
uint8_t *uvc_buffer = s_uvc_device.user_config[1].uvc_buffer;
uint32_t uvc_buffer_size = s_uvc_device.user_config[1].uvc_buffer_size;
uvc_fb_t *pic = NULL;
while (1)
{
if (!tud_video_n_streaming(1, 0))
{
already_start = 0;
frame_num = 0;
tx_busy = 0;
vTaskDelay(1);
continue;
}
if (!already_start)
{
already_start = 1;
start_ms = get_time_millis();
}
uint32_t cur = get_time_millis();
if (cur - start_ms < s_uvc_device.interval_ms[1])
{
vTaskDelay(1);
continue;
}
if (tx_busy)
{
uint32_t xfer_done = ulTaskNotifyTake(pdTRUE, 1);
if (xfer_done == 0)
{
continue;
}
++frame_num;
tx_busy = 0;
}
start_ms += s_uvc_device.interval_ms[1];
ESP_LOGD(TAG, "frame %" PRIu32 " taking picture...", frame_num);
pic = s_uvc_device.user_config[1].fb_get_cb(s_uvc_device.user_config[1].cb_ctx);
if (pic)
{
ESP_LOGD(TAG, "Picture taken! Its size was: %zu bytes", pic->len);
}
else
{
ESP_LOGE(TAG, "Failed to capture picture");
continue;
}
if (pic->len > uvc_buffer_size)
{
ESP_LOGW(TAG, "frame size is too big, dropping frame");
s_uvc_device.user_config[1].fb_return_cb(pic, s_uvc_device.user_config[1].cb_ctx);
continue;
}
frame_len = pic->len;
memcpy(uvc_buffer, pic->buf, frame_len);
s_uvc_device.user_config[1].fb_return_cb(pic, s_uvc_device.user_config[1].cb_ctx);
tx_busy = 1;
tud_video_n_frame_xfer(1, 0, (void *)uvc_buffer, frame_len);
ESP_LOGD(TAG, "frame %" PRIu32 " transfer start, size %" PRIu32, frame_num, frame_len);
}
}
#endif
void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx)
{
(void)ctl_idx;
@@ -307,20 +221,11 @@ esp_err_t uvc_device_config(int index, uvc_device_config_t *config)
esp_err_t uvc_device_init(void)
{
ESP_RETURN_ON_FALSE(s_uvc_device.uvc_init[0], ESP_ERR_INVALID_STATE, TAG, "uvc device 0 not init");
#if CONFIG_UVC_SUPPORT_TWO_CAM
ESP_RETURN_ON_FALSE(s_uvc_device.uvc_init[1], ESP_ERR_INVALID_STATE, TAG, "uvc device 1 not init, if not use, please disable CONFIG_UVC_SUPPORT_TWO_CAM");
#endif
#ifdef CONFIG_FORMAT_MJPEG_CAM1
s_uvc_device.format[0] = UVC_FORMAT_JPEG;
#endif
#if CONFIG_UVC_SUPPORT_TWO_CAM
#ifdef CONFIG_FORMAT_MJPEG_CAM2
s_uvc_device.format[1] = UVC_FORMAT_JPEG;
#endif
#endif
// init device stack on configured roothub port
usb_phy_init();
bool usb_init = tusb_init();
@@ -335,10 +240,6 @@ esp_err_t uvc_device_init(void)
#if (CFG_TUD_VIDEO)
core_id = (CONFIG_UVC_CAM1_TASK_CORE < 0) ? tskNO_AFFINITY : CONFIG_UVC_CAM1_TASK_CORE;
xTaskCreatePinnedToCore(video_task, "UVC", 4096, NULL, CONFIG_UVC_CAM1_TASK_PRIORITY, &s_uvc_device.uvc_task_hdl[0], core_id);
#if CONFIG_UVC_SUPPORT_TWO_CAM
core_id = (CONFIG_UVC_CAM2_TASK_CORE < 0) ? tskNO_AFFINITY : CONFIG_UVC_CAM2_TASK_CORE;
xTaskCreatePinnedToCore(video_task2, "UVC2", 4096, NULL, CONFIG_UVC_CAM2_TASK_PRIORITY, &s_uvc_device.uvc_task_hdl[1], core_id);
#endif
#endif
ESP_LOGI(TAG, "UVC Device Start, Version: %d.%d.%d", USB_DEVICE_UVC_VER_MAJOR, USB_DEVICE_UVC_VER_MINOR, USB_DEVICE_UVC_VER_PATCH);
return ESP_OK;

View File

@@ -107,6 +107,16 @@ menu "OpenIris: WiFi Configuration"
endmenu
menu "OpenIris: Serial Communication Settings"
config UART_PORT_NUMER
int "UART Port number"
default 1
range 1 4
help
The UART port to use for communication
endmenu
menu "OpenIris: LED Configuration"
config LED_DEBUG_ENABLE

View File

@@ -165,7 +165,6 @@ void startWiredMode(bool shouldCloseSerialManager)
#ifndef CONFIG_GENERAL_INCLUDE_UVC_MODE
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;
startWiFiMode();
#else
ESP_LOGI("[MAIN]", "Starting UVC streaming mode.");

915
sdkconfig

File diff suppressed because it is too large Load Diff

2157
sdkconfig.old Normal file

File diff suppressed because it is too large Load Diff