Skip to content

Commit d89ccbe

Browse files
committed
Add swapbuffers
this still seems to encounter some tearing, but it's not clear to me why. It reduces it greatly.
1 parent 8d6d559 commit d89ccbe

3 files changed

Lines changed: 27 additions & 20 deletions

File tree

shared-bindings/uvc/__init__.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,24 @@ STATIC mp_obj_t uvc_disable(void) {
9898
};
9999
STATIC MP_DEFINE_CONST_FUN_OBJ_0(uvc_disable_obj, uvc_disable);
100100

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+
101113

102114
static const mp_rom_map_elem_t uvc_module_globals_table[] = {
103115
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uvc) },
104116
{ MP_ROM_QSTR(MP_QSTR_bitmap), MP_ROM_PTR(&uvc_bitmap_obj) },
105117
{ 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) },
106119
{ MP_ROM_QSTR(MP_QSTR_enable_framebuffer), MP_ROM_PTR(&uvc_enable_framebuffer_obj) },
107120
};
108121

shared-bindings/uvc/__init__.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,4 @@
3030
extern displayio_bitmap_t uvc_bitmap_obj;
3131
bool shared_module_uvc_enable(mp_int_t frame_width, mp_int_t frame_height);
3232
bool shared_module_uvc_disable(void);
33+
void shared_module_uvc_swapbuffers(void);

shared-module/uvc/__init__.c

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "supervisor/shared/tick.h"
1111
#include "device/usbd.h"
1212

13+
static bool do_convert = true;
1314
static unsigned frame_num = 0;
1415
static unsigned tx_busy = 0;
1516
static unsigned interval_ms = 1000 / DEFAULT_FRAME_RATE;
@@ -93,15 +94,15 @@ size_t usb_uvc_descriptor_length(void) {
9394
#endif
9495
}
9596

96-
static void convert_framebuffer(void) {
97+
static void convert_framebuffer_maybe(void) {
98+
if (!do_convert) {
99+
return; // new data not ready yet
100+
}
101+
do_convert = false; // assumes this happens via background, not interrupt
102+
97103
uint8_t *dest = frame_buffer_yuyv;
98104
uint16_t *src = frame_buffer_rgb565;
99105

100-
static int i = 0;
101-
if ((i++) % 100 == 0) {
102-
mp_printf(&mp_plat_print, "convert_framebuffer width=%d height=%d total pixel pairs = %d\n",
103-
uvc_frame_width, uvc_frame_height, uvc_frame_width * uvc_frame_height / 2);
104-
}
105106
for (int i = 0; i < uvc_frame_width * uvc_frame_height / 2; i++) {
106107
uint16_t p1 = IMAGE_GET_RGB565_PIXEL_FAST(src, 0);
107108
uint16_t p2 = IMAGE_GET_RGB565_PIXEL_FAST(src, 1);
@@ -122,6 +123,10 @@ static void convert_framebuffer(void) {
122123
}
123124
}
124125

126+
void shared_module_uvc_swapbuffers(void) {
127+
do_convert = true;
128+
}
129+
125130
size_t usb_uvc_add_descriptor(uint8_t *descriptor_buf, descriptor_counts_t *descriptor_counts, uint8_t *current_interface_string) {
126131
usb_add_interface_string(*current_interface_string, "CircuitPython UVC");
127132
const uint8_t usb_uvc_descriptor[] = {
@@ -144,35 +149,24 @@ size_t usb_uvc_add_descriptor(uint8_t *descriptor_buf, descriptor_counts_t *desc
144149

145150
background_callback_t uvc_cb;
146151

147-
#define printf(...) mp_printf(&mp_plat_print, __VA_ARGS__)
148-
149152
STATIC void uvc_cb_fun(void *unused) {
150153
(void)unused;
151154

152155
static unsigned start_ms = 0;
153156
static unsigned already_sent = 0;
154157

155-
{
156-
static int i;
157-
if (i++ % 100 == 0) {
158-
// printf("usb_uvc_task i=%d, tud_video_n_streaming=%d already_sent=%d start_ms=%d\n", i, tud_video_n_streaming(0, 0), already_sent, start_ms);
159-
}
160-
}
161-
162158
if (!tud_video_n_streaming(0, 0)) {
163159
already_sent = 0;
164160
frame_num = 0;
165-
// printf("not already streaming\n");
166161
return;
167162
}
168163

169164
if (!already_sent) {
170165
already_sent = 1;
171166
start_ms = supervisor_ticks_ms32();
172-
convert_framebuffer();
167+
convert_framebuffer_maybe();
173168
bool result = tud_video_n_frame_xfer(0, 0, (void *)frame_buffer_yuyv, uvc_frame_width * uvc_frame_height * 16 / 8);
174169
(void)result;
175-
// printf("(!already_sent) frame_xfer -> %d\n", (int)result);
176170
}
177171

178172
unsigned cur = supervisor_ticks_ms32();
@@ -186,10 +180,9 @@ STATIC void uvc_cb_fun(void *unused) {
186180
}
187181
start_ms += interval_ms;
188182

189-
convert_framebuffer();
183+
convert_framebuffer_maybe();
190184
bool result = tud_video_n_frame_xfer(0, 0, (void *)frame_buffer_yuyv, uvc_frame_width * uvc_frame_height * 16 / 8);
191185
(void)result;
192-
// printf("frame_xfer -> %d\n", (int)result);
193186
}
194187

195188
void usb_uvc_task(void) {

0 commit comments

Comments
 (0)