Skip to content

Commit e47c58a

Browse files
committed
uvc: Add UVCFramebuffer
This replaces the earlier, Bitmap-based way of interacting with the UVC framebuffer. Typical usage: ```py displayio.release_displays() display = frambufferio.FramebufferDisplay(uvc.UVCFramebuffer()) ``` This works on a MacroPad with a 128x128 framebuffer, but does not work on a QT Py esp32s3. On esp32s3, having the UVC-configuring line alone causes a hard-fault at startup. However, disabling some other USB devices allows it to boot and run code.py: ```py import uvc import usb_hid import usb_midi usb_hid.disable() usb_midi.disable() uvc.enable_framebuffer(64, 64) ``` however, as far as I can tell within qv4l2, the device never actually transmits a frame of data (received frame count never increases). I have not yet analyzed this failure in further detail.
1 parent b9f7566 commit e47c58a

File tree

8 files changed

+295
-23
lines changed

8 files changed

+295
-23
lines changed

shared-bindings/uvc/UVCFramebuffer.c

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2024 Jeff Epler for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "py/obj.h"
28+
#include "py/objproperty.h"
29+
30+
#include "shared-bindings/uvc/__init__.h"
31+
#include "shared-bindings/uvc/UVCFramebuffer.h"
32+
#include "shared-module/displayio/__init__.h"
33+
#include "shared-module/framebufferio/FramebufferDisplay.h"
34+
#include "shared-module/framebufferio/__init__.h"
35+
#include "shared-module/uvc/__init__.h"
36+
#include "shared-module/uvc/UVCFramebuffer.h"
37+
#include "shared-bindings/util.h"
38+
39+
static void check_for_deinit(uvc_uvcframebuffer_obj_t *self) {
40+
if (!shared_module_uvc_uvcframebuffer_get_width(self)) {
41+
raise_deinited_error();
42+
}
43+
}
44+
45+
//| class UVCFramebuffer:
46+
//| """Displays to a USB connected computer using the UVC protocol"""
47+
//|
48+
//| def __new__():
49+
//| """Returns the singleton UVC framebuffer object, if UVC is enabled"""
50+
//
51+
//| def refresh(self) -> None:
52+
//| """Transmits the color data in the buffer to the pixels so that
53+
//| they are shown."""
54+
//| ...
55+
STATIC mp_obj_t uvc_uvcframebuffer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
56+
static const mp_arg_t allowed_args[] = {};
57+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
58+
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
59+
uvc_uvcframebuffer_obj_t *self = &uvc_uvcframebuffer_singleton_obj;
60+
return self;
61+
}
62+
63+
STATIC mp_obj_t uvc_uvcframebuffer_refresh(mp_obj_t self_in) {
64+
uvc_uvcframebuffer_obj_t *self = (uvc_uvcframebuffer_obj_t *)self_in;
65+
check_for_deinit(self);
66+
shared_module_uvc_uvcframebuffer_refresh(self);
67+
return mp_const_none;
68+
}
69+
MP_DEFINE_CONST_FUN_OBJ_1(uvc_uvcframebuffer_refresh_obj, uvc_uvcframebuffer_refresh);
70+
71+
//| width: int
72+
//| """The width of the display, in pixels"""
73+
STATIC mp_obj_t uvc_uvcframebuffer_get_width(mp_obj_t self_in) {
74+
uvc_uvcframebuffer_obj_t *self = (uvc_uvcframebuffer_obj_t *)self_in;
75+
check_for_deinit(self);
76+
return MP_OBJ_NEW_SMALL_INT(shared_module_uvc_uvcframebuffer_get_width(self));
77+
}
78+
MP_DEFINE_CONST_FUN_OBJ_1(uvc_uvcframebuffer_get_width_obj, uvc_uvcframebuffer_get_width);
79+
MP_PROPERTY_GETTER(uvc_uvcframebuffer_width_obj,
80+
(mp_obj_t)&uvc_uvcframebuffer_get_width_obj);
81+
82+
//| height: int
83+
//| """The height of the display, in pixels"""
84+
//|
85+
STATIC mp_obj_t uvc_uvcframebuffer_get_height(mp_obj_t self_in) {
86+
uvc_uvcframebuffer_obj_t *self = (uvc_uvcframebuffer_obj_t *)self_in;
87+
check_for_deinit(self);
88+
return MP_OBJ_NEW_SMALL_INT(shared_module_uvc_uvcframebuffer_get_height(self));
89+
}
90+
MP_DEFINE_CONST_FUN_OBJ_1(uvc_uvcframebuffer_get_height_obj, uvc_uvcframebuffer_get_height);
91+
92+
MP_PROPERTY_GETTER(uvc_uvcframebuffer_height_obj,
93+
(mp_obj_t)&uvc_uvcframebuffer_get_height_obj);
94+
95+
STATIC const mp_rom_map_elem_t uvc_uvcframebuffer_locals_dict_table[] = {
96+
{ MP_ROM_QSTR(MP_QSTR_refresh), MP_ROM_PTR(&uvc_uvcframebuffer_refresh_obj) },
97+
{ MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&uvc_uvcframebuffer_width_obj) },
98+
{ MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&uvc_uvcframebuffer_height_obj) },
99+
};
100+
STATIC MP_DEFINE_CONST_DICT(uvc_uvcframebuffer_locals_dict, uvc_uvcframebuffer_locals_dict_table);
101+
102+
STATIC void uvc_uvcframebuffer_get_bufinfo(mp_obj_t self_in, mp_buffer_info_t *bufinfo) {
103+
shared_module_uvc_uvcframebuffer_get_bufinfo(self_in, bufinfo);
104+
}
105+
106+
// These version exists so that the prototype matches the protocol,
107+
// avoiding a type cast that can hide errors
108+
STATIC void uvc_uvcframebuffer_swapbuffers(mp_obj_t self_in, uint8_t *dirty_row_bitmap) {
109+
(void)dirty_row_bitmap;
110+
shared_module_uvc_uvcframebuffer_refresh(self_in);
111+
}
112+
113+
STATIC void uvc_uvcframebuffer_deinit_proto(mp_obj_t self_in) {
114+
/* NOTHING */
115+
}
116+
117+
STATIC int uvc_uvcframebuffer_get_width_proto(mp_obj_t self_in) {
118+
return shared_module_uvc_uvcframebuffer_get_width(self_in);
119+
}
120+
121+
STATIC int uvc_uvcframebuffer_get_height_proto(mp_obj_t self_in) {
122+
return shared_module_uvc_uvcframebuffer_get_height(self_in);
123+
}
124+
125+
STATIC int uvc_uvcframebuffer_get_native_frames_per_second_proto(mp_obj_t self_in) {
126+
return 10;
127+
}
128+
129+
STATIC bool uvc_uvcframebuffer_get_reverse_pixels_in_word_proto(mp_obj_t self_in) {
130+
return true;
131+
}
132+
133+
134+
STATIC const framebuffer_p_t uvc_uvcframebuffer_proto = {
135+
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuffer)
136+
.get_bufinfo = uvc_uvcframebuffer_get_bufinfo,
137+
.get_width = uvc_uvcframebuffer_get_width_proto,
138+
.get_height = uvc_uvcframebuffer_get_height_proto,
139+
.get_native_frames_per_second = uvc_uvcframebuffer_get_native_frames_per_second_proto,
140+
.swapbuffers = uvc_uvcframebuffer_swapbuffers,
141+
.deinit = uvc_uvcframebuffer_deinit_proto,
142+
.get_reverse_pixels_in_word = uvc_uvcframebuffer_get_reverse_pixels_in_word_proto,
143+
};
144+
145+
STATIC mp_int_t uvc_uvcframebuffer_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
146+
shared_module_uvc_uvcframebuffer_get_bufinfo(self_in, bufinfo);
147+
bufinfo->typecode = 'H';
148+
return 0;
149+
}
150+
151+
MP_DEFINE_CONST_OBJ_TYPE(
152+
uvc_UVCFramebuffer_type,
153+
MP_QSTR_UVCFramebuffer,
154+
MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS,
155+
locals_dict, &uvc_uvcframebuffer_locals_dict,
156+
make_new, uvc_uvcframebuffer_make_new,
157+
buffer, uvc_uvcframebuffer_get_buffer,
158+
protocol, &uvc_uvcframebuffer_proto
159+
);

shared-bindings/uvc/UVCFramebuffer.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2024 Jeff Epler for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#pragma once
28+
29+
typedef struct uvc_uvcframebuffer_obj uvc_uvcframebuffer_obj_t;
30+
31+
extern const mp_obj_type_t uvc_UVCFramebuffer_type;
32+
extern uvc_uvcframebuffer_obj_t uvc_uvcframebuffer_singleton_obj;
33+
34+
void shared_module_uvc_uvcframebuffer_get_bufinfo(uvc_uvcframebuffer_obj_t *self, mp_buffer_info_t *bufinfo);
35+
void shared_module_uvc_uvcframebuffer_refresh(uvc_uvcframebuffer_obj_t *self);
36+
int shared_module_uvc_uvcframebuffer_get_width(uvc_uvcframebuffer_obj_t *self);
37+
int shared_module_uvc_uvcframebuffer_get_height(uvc_uvcframebuffer_obj_t *self);

shared-bindings/uvc/__init__.c

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "py/runtime.h"
2929

3030
#include "shared-bindings/uvc/__init__.h"
31+
#include "shared-bindings/uvc/UVCFramebuffer.h"
3132
#include "shared-module/uvc/__init__.h"
3233

3334
//| """Allows streaming bitmaps to a host computer via USB UVC
@@ -98,24 +99,10 @@ STATIC mp_obj_t uvc_disable(void) {
9899
};
99100
STATIC MP_DEFINE_CONST_FUN_OBJ_0(uvc_disable_obj, uvc_disable);
100101

101-
//|
102-
//| def swapbuffers() -> None:
103-
//| """Copy the back framebuffer to the front framebuffer
104-
//|
105-
//| This updates the data transmitted to the host computer via USB."""
106-
//|
107-
STATIC mp_obj_t uvc_swapbuffers(void) {
108-
shared_module_uvc_swapbuffers();
109-
return mp_const_none;
110-
};
111-
STATIC MP_DEFINE_CONST_FUN_OBJ_0(uvc_swapbuffers_obj, uvc_swapbuffers);
112-
113-
114102
static const mp_rom_map_elem_t uvc_module_globals_table[] = {
115103
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uvc) },
116-
{ MP_ROM_QSTR(MP_QSTR_bitmap), MP_ROM_PTR(&uvc_bitmap_obj) },
104+
{ MP_ROM_QSTR(MP_QSTR_UVCFramebuffer), MP_ROM_PTR(&uvc_UVCFramebuffer_type) },
117105
{ MP_ROM_QSTR(MP_QSTR_disable), MP_ROM_PTR(&uvc_disable_obj) },
118-
{ MP_ROM_QSTR(MP_QSTR_swapbuffers), MP_ROM_PTR(&uvc_swapbuffers_obj) },
119106
{ MP_ROM_QSTR(MP_QSTR_enable_framebuffer), MP_ROM_PTR(&uvc_enable_framebuffer_obj) },
120107
};
121108

shared-module/uvc/UVCFramebuffer.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2024 Jeff Epler for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "shared-module/uvc/__init__.h"
28+
#include "shared-module/uvc/UVCFramebuffer.h"
29+
#include "shared-bindings/uvc/UVCFramebuffer.h"
30+
#include "shared-bindings/uvc/__init__.h"
31+
32+
uvc_uvcframebuffer_obj_t uvc_uvcframebuffer_singleton_obj = {
33+
.base = { &uvc_UVCFramebuffer_type },
34+
};
35+
36+
void shared_module_uvc_uvcframebuffer_get_bufinfo(uvc_uvcframebuffer_obj_t *self, mp_buffer_info_t *bufinfo) {
37+
bufinfo->buf = uvc_framebuffer_rgb565;
38+
bufinfo->len = 2 * uvc_frame_width * uvc_frame_height;
39+
}
40+
41+
void shared_module_uvc_uvcframebuffer_refresh(uvc_uvcframebuffer_obj_t *self) {
42+
shared_module_uvc_swapbuffers();
43+
}
44+
45+
int shared_module_uvc_uvcframebuffer_get_width(uvc_uvcframebuffer_obj_t *self) {
46+
return uvc_frame_width;
47+
}
48+
49+
int shared_module_uvc_uvcframebuffer_get_height(uvc_uvcframebuffer_obj_t *self) {
50+
return uvc_frame_height;
51+
}

shared-module/uvc/UVCFramebuffer.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2024 Jeff Epler for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#pragma once
28+
29+
#include "py/obj.h"
30+
31+
typedef struct uvc_uvcframebuffer_obj {
32+
mp_obj_base_t base;
33+
} uvc_uvcframebuffer_obj_t;

shared-module/uvc/__init__.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ static unsigned interval_ms = 1000 / DEFAULT_FRAME_RATE;
1717

1818
// TODO must dynamically allocate this, otherwise everyone pays for it
1919
static uint8_t *frame_buffer_yuyv;
20-
static uint16_t *frame_buffer_rgb565;
20+
uint16_t *uvc_framebuffer_rgb565;
2121

2222
displayio_bitmap_t uvc_bitmap_obj = {
2323
.base = {.type = &displayio_bitmap_type },
@@ -29,7 +29,7 @@ displayio_bitmap_t uvc_bitmap_obj = {
2929
};
3030

3131
static bool uvc_is_enabled = false;
32-
static mp_int_t uvc_frame_width, uvc_frame_height;
32+
uint16_t uvc_frame_width, uvc_frame_height;
3333

3434
bool shared_module_uvc_enable(mp_int_t frame_width, mp_int_t frame_height) {
3535
if (tud_connected()) {
@@ -50,16 +50,16 @@ bool shared_module_uvc_enable(mp_int_t frame_width, mp_int_t frame_height) {
5050
size_t framebuffer_size = uvc_frame_width * uvc_frame_height * 2;
5151
frame_buffer_yuyv = port_malloc(framebuffer_size, false);
5252
uint32_t *frame_buffer_rgb565_uint32 = port_malloc(framebuffer_size, false);
53-
frame_buffer_rgb565 = (uint16_t *)frame_buffer_rgb565_uint32;
53+
uvc_framebuffer_rgb565 = (uint16_t *)frame_buffer_rgb565_uint32;
5454

55-
if (!frame_buffer_yuyv || !frame_buffer_rgb565) {
55+
if (!frame_buffer_yuyv || !uvc_framebuffer_rgb565) {
5656
// this will free either of the buffers allocated just above, in
5757
// case one succeeded and the other failed.
5858
shared_module_uvc_disable();
5959
m_malloc_fail(2 * framebuffer_size);
6060
}
6161
memset(frame_buffer_yuyv, 0, framebuffer_size);
62-
memset(frame_buffer_rgb565, 0, framebuffer_size);
62+
memset(uvc_framebuffer_rgb565, 0, framebuffer_size);
6363

6464
uvc_bitmap_obj.data = (uint32_t *)frame_buffer_rgb565_uint32;
6565
uvc_bitmap_obj.width = uvc_frame_width;
@@ -78,9 +78,9 @@ bool shared_module_uvc_disable(void) {
7878
uvc_bitmap_obj.data = NULL; // should be redundant
7979
uvc_is_enabled = false;
8080
port_free(frame_buffer_yuyv);
81-
port_free(frame_buffer_rgb565);
81+
port_free(uvc_framebuffer_rgb565);
8282
frame_buffer_yuyv = NULL;
83-
frame_buffer_rgb565 = NULL;
83+
uvc_framebuffer_rgb565 = NULL;
8484
return true;
8585
}
8686

@@ -103,7 +103,7 @@ static void convert_framebuffer_maybe(void) {
103103
do_convert = false; // assumes this happens via background, not interrupt
104104

105105
uint8_t *dest = frame_buffer_yuyv;
106-
uint16_t *src = frame_buffer_rgb565;
106+
uint16_t *src = uvc_framebuffer_rgb565;
107107

108108
for (int i = 0; i < uvc_frame_width * uvc_frame_height / 2; i++) {
109109
uint16_t p1 = IMAGE_GET_RGB565_PIXEL_FAST(src, 0);

shared-module/uvc/__init__.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,6 @@ bool usb_uvc_enabled(void);
3636
size_t usb_uvc_descriptor_length(void);
3737
size_t usb_uvc_add_descriptor(uint8_t *descriptor_buf, descriptor_counts_t *descriptor_counts, uint8_t *current_interface_string);
3838
void usb_uvc_task(void);
39+
40+
extern uint16_t uvc_frame_width, uvc_frame_height;
41+
extern uint16_t *uvc_framebuffer_rgb565;

supervisor/supervisor.mk

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ ifeq ($(CIRCUITPY_USB),1)
162162
SRC_SUPERVISOR += \
163163
shared-bindings/uvc/__init__.c \
164164
shared-module/uvc/__init__.c \
165+
shared-bindings/uvc/UVCFramebuffer.c \
166+
shared-module/uvc/UVCFramebuffer.c \
165167
lib/tinyusb/src/class/video/video_device.c \
166168

167169
CFLAGS += -DCFG_TUD_VIDEO=1 -DCFG_TUD_VIDEO_STREAMING=1 -DCFG_TUD_VIDEO_STREAMING_EP_BUFSIZE=256 -DCFG_TUD_VIDEO_STREAMING_BULK=1

0 commit comments

Comments
 (0)