Skip to content

Commit 1fdbed1

Browse files
committed
添加deepcraft-ai示例工程
1 parent 03afc5f commit 1fdbed1

375 files changed

Lines changed: 143953 additions & 8524 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/action.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ jobs:
6565
- {RTT_BSP: "Edgi_Talk_CherryUSB/Edgi_Talk_Extend_Screen"}
6666
- {RTT_BSP: "Edgi_Talk_CherryUSB/Edgi_Talk_M55_USB_UVC"}
6767
- {RTT_BSP: "Edgi_Talk_CherryUSB/Edgi_Talk_USB_Deepcraft"}
68+
- {RTT_BSP: "Edgi_Talk_M55_DEEPCRAFT_Deploy_Vision"}
6869
- {RTT_BSP: "Edgi_Talk_M55_CoreMark"}
6970
- {RTT_BSP: "Edgi_Talk_M33_CDC_Echo"}
7071
- {RTT_BSP: "Edgi_Talk_M33_HyperRam"}
Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,48 @@
11
from building import *
22

33
cwd = GetCurrentDir()
4+
project_root = Dir('#').abspath.replace('\\', '/')
5+
cherryusb_root = project_root + '/libraries/components/CherryUSB-1.6.0'
6+
build_uvc_from_source = GetDepend(['RT_CHERRYUSB_HOST_BUILD_FROM_SOURCE'])
7+
48
src = [
59
'usbh_uvc_app.c',
610
'usbh_uvc_display.c',
711
'tjpgd.c',
812
]
913

14+
cpp_path = [
15+
cwd,
16+
project_root + '/applications',
17+
]
18+
19+
libs = []
20+
libpath = []
21+
22+
if build_uvc_from_source:
23+
src += [
24+
'usbh_uvc_port.c',
25+
'usbh_uvc_stream.c',
26+
]
27+
cpp_path += [
28+
cherryusb_root + '/common',
29+
cherryusb_root + '/core',
30+
cherryusb_root + '/class/hub',
31+
cherryusb_root + '/class/video',
32+
cherryusb_root + '/third_party/cherrymp',
33+
cherryusb_root + '/port/dwc2',
34+
]
35+
else:
36+
libpath = [cwd]
37+
libs = ['usbh_uvc']
38+
1039
group = DefineGroup(
1140
'UsbUvc',
1241
src,
1342
depend=['RT_CHERRYUSB_HOST_VIDEO'],
14-
CPPPATH=[cwd],
15-
LIBPATH=[cwd],
16-
LIBS=['usbh_uvc_port', 'usbh_uvc_stream'],
43+
CPPPATH=cpp_path,
44+
LIBPATH=libpath,
45+
LIBS=libs,
1746
)
1847

1948
Return('group')
171 KB
Binary file not shown.
-16.7 KB
Binary file not shown.
-245 KB
Binary file not shown.

libraries/Common/board/ports/usb/usbh_uvc_app.c

Lines changed: 85 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,33 @@
77
#include <rtdevice.h>
88
#include "usbh_uvc_stream.h"
99

10+
#ifdef BSP_USING_DEEPCRAFT_AI
11+
#include "uvc_ai_app.h"
12+
#else
13+
static void uvc_ai_app_enforce_mode(uint8_t *fmt, uint16_t *width, uint16_t *height)
14+
{
15+
(void)fmt;
16+
(void)width;
17+
(void)height;
18+
}
19+
20+
static int uvc_ai_app_start(uint16_t src_width, uint16_t src_height)
21+
{
22+
(void)src_width;
23+
(void)src_height;
24+
return 0;
25+
}
26+
27+
static void uvc_ai_app_process_frame(const struct usbh_videoframe *frame)
28+
{
29+
(void)frame;
30+
}
31+
32+
static void uvc_ai_app_stop(void)
33+
{
34+
}
35+
#endif
36+
1037
#undef USB_DBG_TAG
1138
#define USB_DBG_TAG "uvc_app"
1239
#include "usb_log.h"
@@ -32,10 +59,44 @@ static volatile uint8_t uvc_app_running;
3259
static volatile uint32_t g_uvc_display_fps;
3360
static volatile uint32_t g_uvc_display_drop_count;
3461

62+
static void uvc_filter_empty_formats(struct usbh_video *video_class)
63+
{
64+
uint8_t read_idx;
65+
uint8_t write_idx;
66+
67+
if (video_class == RT_NULL) {
68+
return;
69+
}
70+
71+
/*
72+
* Some cameras expose an extra VS format entry with zero frames.
73+
* Keep CherryUSB core unchanged and compact valid entries here,
74+
* so usbh_video_open() does not pick an empty format.
75+
*/
76+
write_idx = 0U;
77+
for (read_idx = 0U; read_idx < video_class->num_of_formats; read_idx++) {
78+
if (video_class->format[read_idx].num_of_frames == 0U) {
79+
continue;
80+
}
81+
82+
if (write_idx != read_idx) {
83+
video_class->format[write_idx] = video_class->format[read_idx];
84+
}
85+
write_idx++;
86+
}
87+
88+
if (write_idx != video_class->num_of_formats) {
89+
USB_LOG_WRN("UVC filter empty format: %u -> %u\r\n",
90+
video_class->num_of_formats, write_idx);
91+
video_class->num_of_formats = write_idx;
92+
}
93+
}
94+
3595
/* ---------- CherryUSB video class callbacks ---------- */
3696

3797
void usbh_video_run(struct usbh_video *video_class)
3898
{
99+
uvc_filter_empty_formats(video_class);
39100
USB_LOG_INFO("UVC device connected\r\n");
40101
usbh_video_list_info(video_class);
41102
}
@@ -52,15 +113,6 @@ void usbh_video_stop(struct usbh_video *video_class)
52113
extern volatile uint32_t g_uvc_fps;
53114
extern volatile uint32_t uvc_transfer_count;
54115
extern volatile uint32_t video_complete_count;
55-
extern volatile uint32_t uvc_dbg_eof_count;
56-
extern volatile uint32_t uvc_dbg_fid_toggle;
57-
extern volatile uint32_t uvc_dbg_empty_pkt;
58-
extern volatile uint32_t uvc_dbg_data_pkt;
59-
extern volatile uint32_t uvc_dbg_last_eof_offset;
60-
extern volatile uint32_t uvc_dbg_frame_done;
61-
extern volatile uint32_t uvc_dbg_err_bit;
62-
extern volatile uint32_t uvc_dbg_payload_bytes;
63-
extern volatile uint32_t uvc_dbg_hdronly_pkt;
64116

65117
static void uvc_display_fps_record(void)
66118
{
@@ -104,16 +156,10 @@ static void uvc_frame_keep_latest(struct usbh_videoframe **frame)
104156
static void uvc_fps_thread_entry(void *arg)
105157
{
106158
while (uvc_app_running) {
107-
USB_LOG_INFO("UVC fps:%d disp:%d drop:%u urb:%d eof:%d fid:%d err:%d empty:%d data:%d hdronly:%d payload:%d done:%d last_off:%u\r\n",
159+
USB_LOG_INFO("UVC fps:%d disp:%d drop:%u urb:%d\r\n",
108160
(int)g_uvc_fps, (int)g_uvc_display_fps,
109161
(unsigned)g_uvc_display_drop_count,
110-
(int)video_complete_count,
111-
(int)uvc_dbg_eof_count, (int)uvc_dbg_fid_toggle,
112-
(int)uvc_dbg_err_bit, (int)uvc_dbg_empty_pkt,
113-
(int)uvc_dbg_data_pkt,
114-
(int)uvc_dbg_hdronly_pkt, (int)uvc_dbg_payload_bytes,
115-
(int)uvc_dbg_frame_done,
116-
(unsigned)uvc_dbg_last_eof_offset);
162+
(int)video_complete_count);
117163
rt_thread_mdelay(3000);
118164
}
119165
}
@@ -132,6 +178,7 @@ static void uvc_frame_thread_entry(void *arg)
132178

133179
/* initialise display output */
134180
uvc_display_init();
181+
(void)uvc_ai_app_start(uvc_cam_w, uvc_cam_h);
135182

136183
while (uvc_app_running) {
137184
ret = usbh_video_stream_dequeue(&frame, RT_TICK_PER_SECOND);
@@ -149,6 +196,7 @@ static void uvc_frame_thread_entry(void *arg)
149196
}
150197

151198
usbh_video_stream_get_info(&stream_w, &stream_h, RT_NULL);
199+
uvc_ai_app_process_frame(frame);
152200

153201
/* render frame to LCD */
154202
uvc_display_frame(frame,
@@ -158,14 +206,18 @@ static void uvc_frame_thread_entry(void *arg)
158206

159207
usbh_video_stream_enqueue(frame);
160208
}
209+
210+
uvc_ai_app_stop();
161211
}
162212

163213
/* ---------- msh commands ---------- */
164214

165215
static int cmd_usbh_uvc_start(int argc, char **argv)
166216
{
167217
uint8_t fmt = USBH_VIDEO_FORMAT_UNCOMPRESSED; /* default: YUYV */
168-
uint16_t w = 640, h = 480;
218+
uint16_t w = 320;
219+
uint16_t h = 240;
220+
uint32_t frame_bufsize = UVC_FRAME_BUF_SIZE;
169221
int ret;
170222

171223
if (uvc_app_running) {
@@ -181,14 +233,27 @@ static int cmd_usbh_uvc_start(int argc, char **argv)
181233
h = atoi(argv[3]);
182234
}
183235

236+
uvc_ai_app_enforce_mode(&fmt, &w, &h);
237+
184238
USB_LOG_INFO("UVC start: %ux%u format=%s\r\n", w, h,
185239
fmt == USBH_VIDEO_FORMAT_MJPEG ? "mjpeg" : "yuyv");
186240

241+
if (fmt == USBH_VIDEO_FORMAT_UNCOMPRESSED) {
242+
uint32_t yuyv_size = (uint32_t)w * (uint32_t)h * 2U;
243+
244+
if ((w == 0U) || (h == 0U) || (yuyv_size > UVC_FRAME_BUF_SIZE)) {
245+
USB_LOG_ERR("Invalid YUYV frame size: %ux%u (%lu)\r\n",
246+
w, h, (unsigned long)yuyv_size);
247+
return -RT_EINVAL;
248+
}
249+
frame_bufsize = yuyv_size;
250+
}
251+
187252
/* initialise frame pool */
188253
{
189254
for (uint32_t i = 0; i < UVC_FRAME_BUF_COUNT; i++) {
190255
frame_pool[i].frame_buf = frame_buffer[i];
191-
frame_pool[i].frame_bufsize = UVC_FRAME_BUF_SIZE;
256+
frame_pool[i].frame_bufsize = frame_bufsize;
192257
}
193258
}
194259

@@ -213,7 +278,7 @@ static int cmd_usbh_uvc_start(int argc, char **argv)
213278
if (t) rt_thread_startup(t);
214279

215280
t = rt_thread_create("uvc_frm", uvc_frame_thread_entry, NULL,
216-
8192, 22, 10);
281+
65536, 22, 10);
217282
if (t) rt_thread_startup(t);
218283

219284
/* start the video stream (frames are queued inside stream_start) */

libraries/Common/board/ports/usb/usbh_uvc_display.c

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "cy_graphics.h"
1414
#include "usbh_uvc_stream.h"
1515
#include "tjpgd.h"
16+
#include "usbh_uvc_display_hook.h"
1617

1718
#undef USB_DBG_TAG
1819
#define USB_DBG_TAG "uvc_disp"
@@ -28,20 +29,28 @@
2829
#define UVC_ITCM_SECTION __attribute__((section(".cy_itcm")))
2930
#define UVC_DTCM_SECTION __attribute__((section(".cy_dtcm")))
3031
#define UVC_SHARED_SECTION __attribute__((section(".m33_m55_shared_hyperram")))
32+
#define UVC_RGB565_STAGE_SECTION __attribute__((section(".cy_uvc_rgb565_data")))
3133

3234
#define UVC_MJPEG_WORKBUF_SIZE 4096U
3335
#define UVC_MJPEG_MAX_FRAME_SIZE (128U * 1024U)
3436
#define UVC_MJPEG_MAX_WIDTH 640U
3537
#define UVC_MJPEG_MAX_HEIGHT 480U
3638
#define UVC_MJPEG_MAX_PIXELS (UVC_MJPEG_MAX_WIDTH * UVC_MJPEG_MAX_HEIGHT)
39+
#define UVC_YUYV_STAGE_W 320U
40+
#define UVC_YUYV_STAGE_H 240U
41+
#define UVC_YUYV_STAGE_PIXELS (UVC_YUYV_STAGE_W * UVC_YUYV_STAGE_H)
42+
#define UVC_YUYV_STAGE_BYTES (UVC_YUYV_STAGE_PIXELS * sizeof(uint16_t))
3743

3844
static uint16_t *lcd_fb; /* pointer into LCD framebuffer */
3945
static uint32_t lcd_fb_size; /* bytes */
4046
static rt_bool_t g_uvc_lcd_hw_ready;
4147

4248
static GFXSS_Type *g_uvc_gfxbase = (GFXSS_Type*)GFXSS;
4349
static cy_stc_gfx_context_t g_uvc_gfx_context;
44-
CY_SECTION(".cy_gpu_buf") static uint8_t g_uvc_lcd_fb_mem[LCD_BUF_SIZE] __attribute__((aligned(128))) = {0};
50+
/* Reuse LCD driver's framebuffer instead of allocating an additional 800x512 RGB565 surface. */
51+
extern uint8_t graphics_buffer[LCD_BUF_SIZE];
52+
static uvc_display_overlay_cb_t g_uvc_overlay_cb;
53+
static void *g_uvc_overlay_cb_ctx;
4554

4655
struct uvc_update_rect {
4756
uint16_t x;
@@ -108,6 +117,8 @@ static UVC_DTCM_SECTION int32_t g_uvc_v_to_g_lut[256];
108117
static UVC_DTCM_SECTION uint8_t g_uvc_mjpeg_diag_budget = 8U;
109118
static UVC_SHARED_SECTION uint16_t g_uvc_mjpeg_rgb565[UVC_MJPEG_MAX_PIXELS];
110119
static UVC_SHARED_SECTION uint8_t g_uvc_mjpeg_frame[UVC_MJPEG_MAX_FRAME_SIZE];
120+
/* Keep a 320x240 RGB565 draw-stage buffer in shared SoCMEM to reduce YUV conversion load. */
121+
static UVC_RGB565_STAGE_SECTION uint16_t g_uvc_yuyv_stage_rgb565[UVC_YUYV_STAGE_PIXELS];
111122

112123
#define UVC_MJPEG_STD_DHT_SIZE 420U
113124

@@ -1047,8 +1058,8 @@ static UVC_ITCM_SECTION rt_err_t uvc_display_hw_init(void)
10471058
/* LCD driver is responsible for GFXSS/panel initialization. */
10481059
memset(&g_uvc_gfx_context, 0, sizeof(g_uvc_gfx_context));
10491060

1050-
lcd_fb = (uint16_t *)g_uvc_lcd_fb_mem;
1051-
lcd_fb_size = sizeof(g_uvc_lcd_fb_mem);
1061+
lcd_fb = (uint16_t *)graphics_buffer;
1062+
lcd_fb_size = LCD_BUF_SIZE;
10521063
memset(lcd_fb, 0, lcd_fb_size);
10531064

10541065
g_uvc_lcd_hw_ready = RT_TRUE;
@@ -1061,8 +1072,8 @@ static UVC_ITCM_SECTION rt_err_t uvc_display_refresh_fb_info(void)
10611072
return -RT_ERROR;
10621073
}
10631074

1064-
lcd_fb = (uint16_t *)g_uvc_lcd_fb_mem;
1065-
lcd_fb_size = sizeof(g_uvc_lcd_fb_mem);
1075+
lcd_fb = (uint16_t *)graphics_buffer;
1076+
lcd_fb_size = LCD_BUF_SIZE;
10661077
return RT_EOK;
10671078
}
10681079

@@ -1326,6 +1337,41 @@ static UVC_ITCM_SECTION void uvc_display_yuyv(const uint8_t *src, uint32_t src_s
13261337
return;
13271338

13281339
uvc_display_prepare_yuv_lut();
1340+
if ((src_w == UVC_YUYV_STAGE_W) && (src_h == UVC_YUYV_STAGE_H)) {
1341+
uint16_t *dst = g_uvc_yuyv_stage_rgb565;
1342+
1343+
if (src_size < (uint32_t)UVC_YUYV_STAGE_W * UVC_YUYV_STAGE_H * 2U) {
1344+
return;
1345+
}
1346+
1347+
for (uint16_t y = 0; y < UVC_YUYV_STAGE_H; y++) {
1348+
const uint8_t *srow = src + (uint32_t)y * UVC_YUYV_STAGE_W * 2U;
1349+
uint16_t *drow = dst + (uint32_t)y * UVC_YUYV_STAGE_W;
1350+
1351+
for (uint16_t pair = 0; pair < (UVC_YUYV_STAGE_W / 2U); pair++) {
1352+
uint8_t y0 = srow[0];
1353+
uint8_t u = srow[1];
1354+
uint8_t y1 = srow[2];
1355+
uint8_t v = srow[3];
1356+
int32_t u_to_b = g_uvc_u_to_b_lut[u];
1357+
int32_t u_to_g = g_uvc_u_to_g_lut[u];
1358+
int32_t v_to_r = g_uvc_v_to_r_lut[v];
1359+
int32_t v_to_g = g_uvc_v_to_g_lut[v];
1360+
1361+
drow[0] = yuv_to_rgb565_fast(y0, u_to_b, u_to_g, v_to_r, v_to_g);
1362+
drow[1] = yuv_to_rgb565_fast(y1, u_to_b, u_to_g, v_to_r, v_to_g);
1363+
1364+
srow += 4;
1365+
drow += 2;
1366+
}
1367+
}
1368+
1369+
uvc_display_rgb565(g_uvc_yuyv_stage_rgb565,
1370+
UVC_YUYV_STAGE_BYTES,
1371+
UVC_YUYV_STAGE_W, UVC_YUYV_STAGE_H);
1372+
return;
1373+
}
1374+
13291375
if (uvc_display_prepare_geometry(src_w, src_h) != RT_EOK) {
13301376
return;
13311377
}
@@ -1388,6 +1434,32 @@ int uvc_display_init(void)
13881434
return 0;
13891435
}
13901436

1437+
void uvc_display_set_overlay_callback(uvc_display_overlay_cb_t cb, void *user_ctx)
1438+
{
1439+
g_uvc_overlay_cb = cb;
1440+
g_uvc_overlay_cb_ctx = user_ctx;
1441+
}
1442+
1443+
static void uvc_display_run_overlay_callback(void)
1444+
{
1445+
uvc_display_overlay_info_t info;
1446+
1447+
if ((g_uvc_overlay_cb == RT_NULL) || (lcd_fb == RT_NULL)) {
1448+
return;
1449+
}
1450+
1451+
info.framebuffer = lcd_fb;
1452+
info.lcd_width = LCD_W;
1453+
info.lcd_height = LCD_H;
1454+
info.src_width = g_uvc_display_ctx.src_w;
1455+
info.src_height = g_uvc_display_ctx.src_h;
1456+
info.dst_width = g_uvc_display_ctx.dst_w;
1457+
info.dst_height = g_uvc_display_ctx.dst_h;
1458+
info.dst_y_offset = g_uvc_display_ctx.y_offset;
1459+
1460+
g_uvc_overlay_cb(&info, g_uvc_overlay_cb_ctx);
1461+
}
1462+
13911463
UVC_ITCM_SECTION void uvc_display_frame(struct usbh_videoframe *frame,
13921464
uint16_t src_w, uint16_t src_h)
13931465
{
@@ -1415,6 +1487,7 @@ UVC_ITCM_SECTION void uvc_display_frame(struct usbh_videoframe *frame,
14151487

14161488
/* YUYV rendering */
14171489
uvc_display_yuyv(frame->frame_buf, frame->frame_size, src_w, src_h);
1490+
uvc_display_run_overlay_callback();
14181491

14191492
/* Flush only the active image band to reduce LCD transfer time. */
14201493
(void)uvc_display_flush(&g_uvc_display_ctx.update_rect);

0 commit comments

Comments
 (0)