Initial commit
This commit is contained in:
commit
cf3f9e9e85
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
build/
|
||||
.idea/
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "pico-ice-sdk"]
|
||||
path = pico-ice-sdk
|
||||
url = https://github.com/tinyvision-ai-inc/pico-ice-sdk.git
|
16
CMakeLists.txt
Normal file
16
CMakeLists.txt
Normal file
@ -0,0 +1,16 @@
|
||||
cmake_minimum_required(VERSION 3.13...3.27)
|
||||
|
||||
include(pico_sdk_import.cmake)
|
||||
|
||||
project(usb-video C CXX ASM)
|
||||
pico_sdk_init()
|
||||
|
||||
add_subdirectory(pico-ice-sdk)
|
||||
|
||||
add_executable(usb-video main.cpp usb_descriptors.c)
|
||||
target_link_libraries(usb-video pico_ice_sdk pico_ice_usb pico_stdio_usb pico_bootsel_via_double_reset)
|
||||
target_include_directories(usb-video PUBLIC ${CMAKE_CURRENT_LIST_DIR} ${CMAKE_BINARY_DIR})
|
||||
|
||||
pico_add_extra_outputs(usb-video)
|
||||
pico_enable_stdio_usb(usb-video 0)
|
||||
pico_enable_stdio_uart(usb-video 0)
|
133
main.cpp
Normal file
133
main.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
#include <ice_fpga.h>
|
||||
#include <ice_led.h>
|
||||
#include <ice_usb.h>
|
||||
|
||||
#include <tusb.h>
|
||||
#include <bsp/board_api.h>
|
||||
|
||||
#include <pico/stdio.h>
|
||||
#include <hardware/gpio.h>
|
||||
#include <hardware/uart.h>
|
||||
|
||||
static void video_task();
|
||||
|
||||
int main()
|
||||
{
|
||||
stdio_init_all();
|
||||
|
||||
uart_init(uart0, 115200);
|
||||
gpio_set_function(0, GPIO_FUNC_UART);
|
||||
gpio_set_function(1, GPIO_FUNC_UART);
|
||||
|
||||
ice_led_init();
|
||||
ice_usb_init();
|
||||
|
||||
ice_fpga_init(12);
|
||||
ice_fpga_start();
|
||||
|
||||
tud_init(0);
|
||||
|
||||
if (board_init_after_tusb)
|
||||
{
|
||||
board_init_after_tusb();
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
tud_task();
|
||||
video_task();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int interval_ms = 1000 / FRAME_RATE;
|
||||
static unsigned int frame_num = 0;
|
||||
static bool tx_busy = false;
|
||||
|
||||
static uint8_t frame_buffer[FRAME_WIDTH * FRAME_HEIGHT * 16 / 8] = { };
|
||||
|
||||
static void fill_color_bar(uint8_t* buffer, const unsigned int start_position)
|
||||
{
|
||||
static constexpr uint8_t bar_color[8][4] =
|
||||
{
|
||||
/* Y, U, Y, V */
|
||||
{ 235, 128, 235, 128 }, /* 100% White */
|
||||
{ 219, 16, 219, 138 }, /* Yellow */
|
||||
{ 188, 154, 188, 16 }, /* Cyan */
|
||||
{ 173, 42, 173, 26 }, /* Green */
|
||||
{ 78, 214, 78, 230 }, /* Magenta */
|
||||
{ 63, 102, 63, 240 }, /* Red */
|
||||
{ 32, 240, 32, 118 }, /* Blue */
|
||||
{ 16, 128, 16, 128 }, /* Black */
|
||||
};
|
||||
|
||||
uint8_t* p;
|
||||
|
||||
const uint8_t* end = &buffer[FRAME_WIDTH * 2];
|
||||
const unsigned int index = (FRAME_WIDTH / 2 - 1) - (start_position % (FRAME_WIDTH / 2));
|
||||
|
||||
p = &buffer[index * 4];
|
||||
for (unsigned int i = 0; i < 8; i++)
|
||||
{
|
||||
for (int j = 0; j < FRAME_WIDTH / (2 * 8); j++)
|
||||
{
|
||||
memcpy(p, &bar_color[i], 4);
|
||||
p += 4;
|
||||
if (p >= end) { p = buffer; }
|
||||
}
|
||||
}
|
||||
|
||||
p = &buffer[FRAME_WIDTH * 2];
|
||||
for (unsigned int i = 1; i < FRAME_HEIGHT; i++)
|
||||
{
|
||||
memcpy(p, buffer, FRAME_WIDTH * 2);
|
||||
p += FRAME_WIDTH * 2;
|
||||
}
|
||||
}
|
||||
|
||||
void video_task()
|
||||
{
|
||||
static bool already_sent = false;
|
||||
static unsigned int start_ms = 0;
|
||||
|
||||
// don't send data if not streaming
|
||||
if (!tud_video_n_streaming(0, 0))
|
||||
{
|
||||
already_sent = false;
|
||||
frame_num = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!already_sent)
|
||||
{
|
||||
already_sent = true;
|
||||
tx_busy = true;
|
||||
start_ms = board_millis();
|
||||
|
||||
fill_color_bar(frame_buffer, frame_num);
|
||||
|
||||
tud_video_n_frame_xfer(0, 0, frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16 / 8);
|
||||
}
|
||||
|
||||
const unsigned int cur = board_millis();
|
||||
if (cur - start_ms < interval_ms) { return; }
|
||||
if (tx_busy) { return; }
|
||||
start_ms += interval_ms;
|
||||
tx_busy = true;
|
||||
|
||||
fill_color_bar(frame_buffer, frame_num);
|
||||
tud_video_n_frame_xfer(0, 0, frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16 / 8);
|
||||
}
|
||||
|
||||
void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx)
|
||||
{
|
||||
tx_busy = false;
|
||||
|
||||
frame_num++;
|
||||
}
|
||||
|
||||
int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, const video_probe_and_commit_control_t* parameters)
|
||||
{
|
||||
interval_ms = parameters->dwFrameInterval / 10000;
|
||||
return VIDEO_ERROR_NONE;
|
||||
}
|
1
pico-ice-sdk
Submodule
1
pico-ice-sdk
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 4ebe348ffcb4feb3e2756d101f594679eb02d97c
|
84
pico_sdk_import.cmake
Normal file
84
pico_sdk_import.cmake
Normal file
@ -0,0 +1,84 @@
|
||||
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
|
||||
|
||||
# This can be dropped into an external project to help locate this SDK
|
||||
# It should be include()ed prior to project()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
|
||||
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
|
||||
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
|
||||
endif ()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
|
||||
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
|
||||
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
|
||||
endif ()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
|
||||
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
|
||||
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
|
||||
endif ()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_TAG} AND (NOT PICO_SDK_FETCH_FROM_GIT_TAG))
|
||||
set(PICO_SDK_FETCH_FROM_GIT_TAG $ENV{PICO_SDK_FETCH_FROM_GIT_TAG})
|
||||
message("Using PICO_SDK_FETCH_FROM_GIT_TAG from environment ('${PICO_SDK_FETCH_FROM_GIT_TAG}')")
|
||||
endif ()
|
||||
|
||||
if (PICO_SDK_FETCH_FROM_GIT AND NOT PICO_SDK_FETCH_FROM_GIT_TAG)
|
||||
set(PICO_SDK_FETCH_FROM_GIT_TAG "master")
|
||||
message("Using master as default value for PICO_SDK_FETCH_FROM_GIT_TAG")
|
||||
endif()
|
||||
|
||||
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
|
||||
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
|
||||
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
|
||||
set(PICO_SDK_FETCH_FROM_GIT_TAG "${PICO_SDK_FETCH_FROM_GIT_TAG}" CACHE FILEPATH "release tag for SDK")
|
||||
|
||||
if (NOT PICO_SDK_PATH)
|
||||
if (PICO_SDK_FETCH_FROM_GIT)
|
||||
include(FetchContent)
|
||||
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
|
||||
if (PICO_SDK_FETCH_FROM_GIT_PATH)
|
||||
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
|
||||
endif ()
|
||||
# GIT_SUBMODULES_RECURSE was added in 3.17
|
||||
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0")
|
||||
FetchContent_Declare(
|
||||
pico_sdk
|
||||
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
|
||||
GIT_SUBMODULES_RECURSE FALSE
|
||||
)
|
||||
else ()
|
||||
FetchContent_Declare(
|
||||
pico_sdk
|
||||
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
|
||||
)
|
||||
endif ()
|
||||
|
||||
if (NOT pico_sdk)
|
||||
message("Downloading Raspberry Pi Pico SDK")
|
||||
FetchContent_Populate(pico_sdk)
|
||||
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
|
||||
endif ()
|
||||
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
|
||||
else ()
|
||||
message(FATAL_ERROR
|
||||
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
|
||||
)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||
if (NOT EXISTS ${PICO_SDK_PATH})
|
||||
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
|
||||
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
|
||||
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
|
||||
|
||||
include(${PICO_SDK_INIT_CMAKE_FILE})
|
97
tusb_config.h
Normal file
97
tusb_config.h
Normal file
@ -0,0 +1,97 @@
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
* Copyright (c) 2022 TinyVision.ai Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// pico-ice-sdk
|
||||
#include "boards/pico_ice.h"
|
||||
#include "ice_flash.h"
|
||||
|
||||
// RHPort number used for device can be defined by board.mk, port 0 for pico-ice
|
||||
#define BOARD_DEVICE_RHPORT_NUM 0
|
||||
|
||||
// Device mode with rhport and speed defined by board.mk
|
||||
#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE
|
||||
|
||||
// Either full or high speed supported by RP2040
|
||||
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED
|
||||
|
||||
// Enable Device stack
|
||||
#define CFG_TUD_ENABLED 1
|
||||
|
||||
// Default is max speed that hardware controller could support with on-chip PHY
|
||||
#define CFG_TUD_MAX_SPEED OPT_MODE_FULL_SPEED
|
||||
|
||||
// Device classes
|
||||
#define CFG_TUD_CDC 1
|
||||
#define CFG_TUD_MSC 1
|
||||
#define CFG_TUD_DFU 1
|
||||
#define CFG_TUD_DFU_ALT 2
|
||||
#define CFG_TUD_HID 0
|
||||
#define CFG_TUD_MIDI 0
|
||||
#define CFG_TUD_VENDOR 0
|
||||
#define CFG_TUD_VIDEO 1
|
||||
#define CFG_TUD_VIDEO_STREAMING 1
|
||||
|
||||
// Enable TinyUF2
|
||||
#define ICE_USB_USE_TINYUF2_MSC 1
|
||||
|
||||
// CDC FIFO size of TX and RX and Endpoint buffer size
|
||||
#define CFG_TUD_CDC_RX_BUFSIZE 512
|
||||
#define CFG_TUD_CDC_TX_BUFSIZE 512
|
||||
#define CFG_TUD_CDC_EP_BUFSIZE 512
|
||||
|
||||
// MSC Buffer size of Device Mass storage
|
||||
#define CFG_TUD_MSC_BUFSIZE ICE_FLASH_SECTOR_SIZE
|
||||
|
||||
// Must be a multiple of flash page size
|
||||
#define CFG_TUD_DFU_XFER_BUFSIZE 256
|
||||
|
||||
#define CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE 256
|
||||
#define CFG_TUD_VIDEO_STREAMING_BULK 0
|
||||
|
||||
#define FRAME_WIDTH 32
|
||||
#define FRAME_HEIGHT 18
|
||||
#define FRAME_RATE 60
|
||||
|
||||
// Temporarily here until ice_usb.h has necessary info
|
||||
// TODO: make PR to modify ice_usb.h as needed
|
||||
#define TUD_VIDEO_CAPTURE_DESC_UNCOMPR_LEN (\
|
||||
TUD_VIDEO_DESC_IAD_LEN\
|
||||
/* control */\
|
||||
+ TUD_VIDEO_DESC_STD_VC_LEN\
|
||||
+ (TUD_VIDEO_DESC_CS_VC_LEN + 1/*bInCollection*/)\
|
||||
+ TUD_VIDEO_DESC_CAMERA_TERM_LEN\
|
||||
+ TUD_VIDEO_DESC_OUTPUT_TERM_LEN\
|
||||
/* Interface 1, Alternate 0 */\
|
||||
+ TUD_VIDEO_DESC_STD_VS_LEN\
|
||||
+ (TUD_VIDEO_DESC_CS_VS_IN_LEN + 1/*bNumFormats x bControlSize*/)\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN\
|
||||
+ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN\
|
||||
/* Interface 1, Alternate 1 */\
|
||||
+ TUD_VIDEO_DESC_STD_VS_LEN\
|
||||
+ 7/* Endpoint */\
|
||||
)
|
96
usb_descriptors.c
Normal file
96
usb_descriptors.c
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
* Copyright (c) 2022 TinyVision.ai Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ice_usb.h"
|
||||
|
||||
#define UVC_ENTITY_CAP_INPUT_TERMINAL 0x01
|
||||
#define UVC_ENTITY_CAP_OUTPUT_TERMINAL 0x02
|
||||
#define UVC_CLOCK_FREQUENCY 27000000
|
||||
|
||||
enum { STRID_VIDEO = 5 };
|
||||
|
||||
#define TUD_VIDEO_DESC_CS_VS_FMT_YUY2(_fmtidx, _numfmtdesc, _frmidx, _asrx, _asry, _interlace, _cp) \
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR(_fmtidx, _numfmtdesc, TUD_VIDEO_GUID_YUY2, 16, _frmidx, _asrx, _asry, _interlace, _cp)
|
||||
|
||||
#define TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR(_stridx, _epin, _width, _height, _fps, _epsize) \
|
||||
TUD_VIDEO_DESC_IAD(ITF_NUM_VIDEO_CONTROL, /* 2 Interfaces */ 0x02, _stridx), \
|
||||
/* Video control 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \
|
||||
/* Header: UVC 1.5, length of followed descs, clock (deprecated), streaming interfaces */ \
|
||||
TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \
|
||||
/* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \
|
||||
TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 0), \
|
||||
TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, UVC_ENTITY_CAP_INPUT_TERMINAL, 0), \
|
||||
/* Video stream alt. 0 */ \
|
||||
TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 0, 0, _stridx), \
|
||||
/* Video stream header for without still image capture */ \
|
||||
TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \
|
||||
/*wTotalLength - bLength */ TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\
|
||||
_epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \
|
||||
/*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \
|
||||
/*bmaControls(1)*/0), \
|
||||
/* Video stream format */ \
|
||||
TUD_VIDEO_DESC_CS_VS_FMT_YUY2(/*bFormatIndex*/1, /*bNumFrameDescriptors*/1, \
|
||||
/*bDefaultFrameIndex*/1, 0, 0, 0, /*bCopyProtect*/0), \
|
||||
/* Video stream frame format */ \
|
||||
TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT(/*bFrameIndex */1, 0, _width, _height, \
|
||||
_width * _height * 16, _width * _height * 16 * _fps, \
|
||||
_width * _height * 16 / 8, \
|
||||
(10000000/_fps), (10000000/_fps), (10000000/_fps)*_fps, (10000000/_fps)), \
|
||||
TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \
|
||||
/* VS alt 1 */\
|
||||
TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 1, 1, _stridx), \
|
||||
/* EP */ \
|
||||
TUD_VIDEO_DESC_EP_ISO(_epin, _epsize, 1)
|
||||
|
||||
enum {
|
||||
ITF_NUM_CDC0, ITF_NUM_CDC0_DATA,
|
||||
ITF_NUM_MSC0,
|
||||
ITF_NUM_DFU,
|
||||
ITF_NUM_VIDEO_CONTROL,
|
||||
ITF_NUM_VIDEO_STREAMING,
|
||||
ITF_NUM_TOTAL
|
||||
};
|
||||
|
||||
uint8_t const tud_desc_configuration[CONFIG_TOTAL_LEN] = {
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 500/*mA*/),
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC0, STRID_CDC+0, EPIN+1, 8, EPOUT+2, EPIN+2, 64),
|
||||
TUD_MSC_DESCRIPTOR(ITF_NUM_MSC0, STRID_MSC+0, EPOUT+3, EPIN+3, 64),
|
||||
TUD_DFU_DESCRIPTOR(ITF_NUM_DFU, CFG_TUD_DFU_ALT, STRID_DFU, DFU_ATTR_CAN_DOWNLOAD, 1000, CFG_TUD_DFU_XFER_BUFSIZE),
|
||||
TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR(STRID_VIDEO, EPIN+4, FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE)
|
||||
};
|
||||
|
||||
char const *tud_string_desc[STRID_NUM_TOTAL] = {
|
||||
[STRID_LANGID] = USB_LANG_EN,
|
||||
[STRID_MANUFACTURER] = USB_MANUFACTURER,
|
||||
[STRID_PRODUCT] = USB_PRODUCT,
|
||||
[STRID_SERIAL_NUMBER] = usb_serial_number,
|
||||
[STRID_VENDOR] = USB_VENDOR,
|
||||
[STRID_VIDEO] = "RP2040 camera",
|
||||
[STRID_CDC+0] = "RP2040 logs",
|
||||
[STRID_MSC+0] = "iCE40 MSC (Flash)",
|
||||
[STRID_DFU+0] = "iCE40 DFU (Flash)",
|
||||
[STRID_DFU+1] = "iCE40 DFU (CRAM)"
|
||||
};
|
Loading…
Reference in New Issue
Block a user