Skip to content

Commit da5ba9a

Browse files
committed
Rename & improve doc
1 parent 1c52844 commit da5ba9a

File tree

19 files changed

+310
-308
lines changed

19 files changed

+310
-308
lines changed

ports/espressif/mpconfigport.mk

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ CIRCUITPY_SYNTHIO_MAX_CHANNELS ?= 12
4545
CIRCUITPY_TOUCHIO_USE_NATIVE ?= 1
4646
CIRCUITPY_WATCHDOG ?= 1
4747
CIRCUITPY_WIFI ?= 1
48-
CIRCUITPY_UVC ?= 1
4948

5049
# Conditionally turn off modules/features
5150
ifeq ($(IDF_TARGET),esp32)

ports/raspberrypi/mpconfigport.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ CIRCUITPY_ROTARYIO ?= 1
2323
CIRCUITPY_ROTARYIO_SOFTENCODER = 1
2424
CIRCUITPY_SYNTHIO_MAX_CHANNELS = 12
2525
CIRCUITPY_USB_HOST ?= 1
26-
CIRCUITPY_USB_UVC ?= 1
26+
CIRCUITPY_USB_VIDEO ?= 1
2727

2828
# Things that need to be implemented.
2929
CIRCUITPY_FREQUENCYIO = 0

py/circuitpy_defns.mk

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -393,8 +393,8 @@ endif
393393
ifeq ($(CIRCUITPY_USB_HID),1)
394394
SRC_PATTERNS += usb_hid/%
395395
endif
396-
ifeq ($(CIRCUITPY_USB_UVC),1)
397-
SRC_PATTERNS += uvc/%
396+
ifeq ($(CIRCUITPY_USB_VIDEO),1)
397+
SRC_PATTERNS += usb_video/%
398398
endif
399399
ifeq ($(CIRCUITPY_USB_HOST),1)
400400
SRC_PATTERNS += usb_host/% usb/%

py/circuitpy_mpconfig.mk

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -567,10 +567,8 @@ CFLAGS += -DCIRCUITPY_USB_HID=$(CIRCUITPY_USB_HID)
567567
CIRCUITPY_USB_HID_ENABLED_DEFAULT ?= $(USB_NUM_ENDPOINT_PAIRS_5_OR_GREATER)
568568
CFLAGS += -DCIRCUITPY_USB_HID_ENABLED_DEFAULT=$(CIRCUITPY_USB_HID_ENABLED_DEFAULT)
569569

570-
CIRCUITPY_USB_UVC ?= 0
571-
CIRCUITPY_USB_UVC_ENABLED_DEFAULT ?= 0
572-
CFLAGS += -DCIRCUITPY_USB_UVC_ENABLED_DEFAULT=$(CIRCUITPY_USB_UVC_ENABLED_DEFAULT)
573-
CFLAGS += -DCIRCUITPY_USB_UVC=$(CIRCUITPY_USB_UVC)
570+
CIRCUITPY_USB_VIDEO ?= 0
571+
CFLAGS += -DCIRCUITPY_USB_VIDEO=$(CIRCUITPY_USB_VIDEO)
574572

575573
CIRCUITPY_USB_HOST ?= 0
576574
CFLAGS += -DCIRCUITPY_USB_HOST=$(CIRCUITPY_USB_HOST)
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
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/usb_video/__init__.h"
31+
#include "shared-bindings/usb_video/USBFramebuffer.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/usb_video/__init__.h"
36+
#include "shared-module/usb_video/USBFramebuffer.h"
37+
#include "shared-bindings/util.h"
38+
39+
static void check_for_deinit(usb_video_uvcframebuffer_obj_t *self) {
40+
if (!shared_module_usb_video_uvcframebuffer_get_width(self)) {
41+
raise_deinited_error();
42+
}
43+
}
44+
45+
//| class USBFramebuffer:
46+
//| """Displays to a USB connected computer using the UVC protocol
47+
//|
48+
//| The data in the framebuffer is in RGB565_SWAPPED format.
49+
//|
50+
//| This object is most often used with `framebufferio.FramebufferDisplay`. However,
51+
//| it also supports the `WritableBuffer` protocol and can be accessed
52+
//| as an array of `H` (unsigned 16-bit values)."""
53+
//|
54+
//| def __new__(self):
55+
//| """Returns the singleton framebuffer object, if USB video is enabled"""
56+
STATIC mp_obj_t usb_video_uvcframebuffer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
57+
static const mp_arg_t allowed_args[] = {};
58+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
59+
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
60+
usb_video_uvcframebuffer_obj_t *self = &usb_video_uvcframebuffer_singleton_obj;
61+
return self;
62+
}
63+
64+
//| def refresh(self) -> None:
65+
//| """Transmits the color data in the buffer to the pixels so that
66+
//| they are shown."""
67+
//| ...
68+
STATIC mp_obj_t usb_video_uvcframebuffer_refresh(mp_obj_t self_in) {
69+
usb_video_uvcframebuffer_obj_t *self = (usb_video_uvcframebuffer_obj_t *)self_in;
70+
check_for_deinit(self);
71+
shared_module_usb_video_uvcframebuffer_refresh(self);
72+
return mp_const_none;
73+
}
74+
MP_DEFINE_CONST_FUN_OBJ_1(usb_video_uvcframebuffer_refresh_obj, usb_video_uvcframebuffer_refresh);
75+
76+
//| width: int
77+
//| """The width of the display, in pixels"""
78+
STATIC mp_obj_t usb_video_uvcframebuffer_get_width(mp_obj_t self_in) {
79+
usb_video_uvcframebuffer_obj_t *self = (usb_video_uvcframebuffer_obj_t *)self_in;
80+
check_for_deinit(self);
81+
return MP_OBJ_NEW_SMALL_INT(shared_module_usb_video_uvcframebuffer_get_width(self));
82+
}
83+
MP_DEFINE_CONST_FUN_OBJ_1(usb_video_uvcframebuffer_get_width_obj, usb_video_uvcframebuffer_get_width);
84+
MP_PROPERTY_GETTER(usb_video_uvcframebuffer_width_obj,
85+
(mp_obj_t)&usb_video_uvcframebuffer_get_width_obj);
86+
87+
//| height: int
88+
//| """The height of the display, in pixels"""
89+
//|
90+
STATIC mp_obj_t usb_video_uvcframebuffer_get_height(mp_obj_t self_in) {
91+
usb_video_uvcframebuffer_obj_t *self = (usb_video_uvcframebuffer_obj_t *)self_in;
92+
check_for_deinit(self);
93+
return MP_OBJ_NEW_SMALL_INT(shared_module_usb_video_uvcframebuffer_get_height(self));
94+
}
95+
MP_DEFINE_CONST_FUN_OBJ_1(usb_video_uvcframebuffer_get_height_obj, usb_video_uvcframebuffer_get_height);
96+
97+
MP_PROPERTY_GETTER(usb_video_uvcframebuffer_height_obj,
98+
(mp_obj_t)&usb_video_uvcframebuffer_get_height_obj);
99+
100+
STATIC const mp_rom_map_elem_t usb_video_uvcframebuffer_locals_dict_table[] = {
101+
{ MP_ROM_QSTR(MP_QSTR_refresh), MP_ROM_PTR(&usb_video_uvcframebuffer_refresh_obj) },
102+
{ MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&usb_video_uvcframebuffer_width_obj) },
103+
{ MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&usb_video_uvcframebuffer_height_obj) },
104+
};
105+
STATIC MP_DEFINE_CONST_DICT(usb_video_uvcframebuffer_locals_dict, usb_video_uvcframebuffer_locals_dict_table);
106+
107+
STATIC void usb_video_uvcframebuffer_get_bufinfo(mp_obj_t self_in, mp_buffer_info_t *bufinfo) {
108+
shared_module_usb_video_uvcframebuffer_get_bufinfo(self_in, bufinfo);
109+
}
110+
111+
// These version exists so that the prototype matches the protocol,
112+
// avoiding a type cast that can hide errors
113+
STATIC void usb_video_uvcframebuffer_swapbuffers(mp_obj_t self_in, uint8_t *dirty_row_bitmap) {
114+
(void)dirty_row_bitmap;
115+
shared_module_usb_video_uvcframebuffer_refresh(self_in);
116+
}
117+
118+
STATIC void usb_video_uvcframebuffer_deinit_proto(mp_obj_t self_in) {
119+
/* NOTHING */
120+
}
121+
122+
STATIC int usb_video_uvcframebuffer_get_width_proto(mp_obj_t self_in) {
123+
return shared_module_usb_video_uvcframebuffer_get_width(self_in);
124+
}
125+
126+
STATIC int usb_video_uvcframebuffer_get_height_proto(mp_obj_t self_in) {
127+
return shared_module_usb_video_uvcframebuffer_get_height(self_in);
128+
}
129+
130+
STATIC int usb_video_uvcframebuffer_get_native_frames_per_second_proto(mp_obj_t self_in) {
131+
return 10;
132+
}
133+
134+
STATIC bool usb_video_uvcframebuffer_get_reverse_pixels_in_word_proto(mp_obj_t self_in) {
135+
return true;
136+
}
137+
138+
139+
STATIC const framebuffer_p_t usb_video_uvcframebuffer_proto = {
140+
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuffer)
141+
.get_bufinfo = usb_video_uvcframebuffer_get_bufinfo,
142+
.get_width = usb_video_uvcframebuffer_get_width_proto,
143+
.get_height = usb_video_uvcframebuffer_get_height_proto,
144+
.get_native_frames_per_second = usb_video_uvcframebuffer_get_native_frames_per_second_proto,
145+
.swapbuffers = usb_video_uvcframebuffer_swapbuffers,
146+
.deinit = usb_video_uvcframebuffer_deinit_proto,
147+
.get_reverse_pixels_in_word = usb_video_uvcframebuffer_get_reverse_pixels_in_word_proto,
148+
};
149+
150+
STATIC mp_int_t usb_video_uvcframebuffer_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
151+
shared_module_usb_video_uvcframebuffer_get_bufinfo(self_in, bufinfo);
152+
bufinfo->typecode = 'H';
153+
return 0;
154+
}
155+
156+
MP_DEFINE_CONST_OBJ_TYPE(
157+
usb_video_USBFramebuffer_type,
158+
MP_QSTR_USBFramebuffer,
159+
MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS,
160+
locals_dict, &usb_video_uvcframebuffer_locals_dict,
161+
make_new, usb_video_uvcframebuffer_make_new,
162+
buffer, usb_video_uvcframebuffer_get_buffer,
163+
protocol, &usb_video_uvcframebuffer_proto
164+
);

shared-bindings/uvc/UVCFramebuffer.h renamed to shared-bindings/usb_video/USBFramebuffer.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@
2626

2727
#pragma once
2828

29-
typedef struct uvc_uvcframebuffer_obj uvc_uvcframebuffer_obj_t;
29+
typedef struct usb_video_uvcframebuffer_obj usb_video_uvcframebuffer_obj_t;
3030

31-
extern const mp_obj_type_t uvc_UVCFramebuffer_type;
32-
extern uvc_uvcframebuffer_obj_t uvc_uvcframebuffer_singleton_obj;
31+
extern const mp_obj_type_t usb_video_USBFramebuffer_type;
32+
extern usb_video_uvcframebuffer_obj_t usb_video_uvcframebuffer_singleton_obj;
3333

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);
34+
void shared_module_usb_video_uvcframebuffer_get_bufinfo(usb_video_uvcframebuffer_obj_t *self, mp_buffer_info_t *bufinfo);
35+
void shared_module_usb_video_uvcframebuffer_refresh(usb_video_uvcframebuffer_obj_t *self);
36+
int shared_module_usb_video_uvcframebuffer_get_width(usb_video_uvcframebuffer_obj_t *self);
37+
int shared_module_usb_video_uvcframebuffer_get_height(usb_video_uvcframebuffer_obj_t *self);

shared-bindings/uvc/__init__.c renamed to shared-bindings/usb_video/__init__.c

Lines changed: 49 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -27,42 +27,60 @@
2727
#include "py/obj.h"
2828
#include "py/runtime.h"
2929

30-
#include "shared-bindings/uvc/__init__.h"
31-
#include "shared-bindings/uvc/UVCFramebuffer.h"
32-
#include "shared-module/uvc/__init__.h"
30+
#include "shared-bindings/usb_video/__init__.h"
31+
#include "shared-bindings/usb_video/USBFramebuffer.h"
32+
#include "shared-module/usb_video/__init__.h"
3333

34-
//| """Allows streaming bitmaps to a host computer via USB UVC
34+
//| """Allows streaming bitmaps to a host computer via USB
3535
//|
36-
//| This interface is experimental and may change without notice even in stable
37-
//| versions of CircuitPython."""
36+
//| This makes your CircuitPython device identify to the host computer as a video camera.
37+
//| This mode is also known as "USB UVC".
38+
//|
39+
//| This mode requires 1 IN endpoint. Generally, microcontrollers have a limit on
40+
//| the number of endpoints. If you exceed the number of endpoints, CircuitPython
41+
//| will automatically enter Safe Mode. Even in this case, you may be able to
42+
//| enable USB video by also disabling other USB functions, such as `usb_hid` or
43+
//| `usb_midi`.
44+
//|
45+
//| To enable this mode, you must configure the framebuffer size in ``boot.py`` and then
46+
//| create a display in ``code.py``.
47+
//|
48+
//| .. code-block:: py
49+
//|
50+
//| # boot.py
51+
//| import usb_video
52+
//| usb_video.enable_framebuffer(128, 96)
3853
//|
39-
//| bitmap: displayio.Bitmap
40-
//| """The content of this bitmap image is streamed to the host computer. To change the
41-
//| displayed image, modify the bitmap contents.
54+
//| .. code-block:: py
4255
//|
43-
//| The bitmap content is in RGB565_SWAPPED format. It is converted to "YUYV" format before
44-
//| transmission to the host computer. The "YUYV" format stores a "Y" (luminance) sample
45-
//| for every pixel, but a chromonance (UV) value only for each pair of pixels; due to this,
46-
//| the color of adjacent pixels cannot be fully controlled. For instance, there is no way
47-
//| for the first pixel to be red and the second pixel to be green. However, they can both
48-
//| be different shades of red.
49-
//| """
56+
//| # code.py
57+
//| import usb_video
58+
//| import framebufferio
59+
//| import displayio
60+
//|
61+
//| displayio.release_displays()
62+
//| display = framebufferio.FramebufferDisplay(usb_video.USBFramebuffer())
63+
//|
64+
//| # ... use the display object with displayio Group and TileGrid objects
65+
//|
66+
//| This interface is experimental and may change without notice even in stable
67+
//| versions of CircuitPython."""
5068
//|
5169

5270
//| def enable_framebuffer(width: int, height: int) -> None:
53-
//| """Enable the UVC gadget, setting the given width & height
71+
//| """Enable a USB video framebuffer, setting the given width & height
5472
//|
55-
//| During ``boot.py``, this function may be used to enable the UVC gadget.
73+
//| This function may only be used from ``boot.py``.
5674
//|
5775
//| Width is rounded up to a multiple of 2.
5876
//|
5977
//| After boot.py completes, the framebuffer will be allocated. Total storage
6078
//| of 4×``width``×``height`` bytes is required, reducing the amount available
61-
//| for Python objects. If the allocation fails, a note will be written in boot.py
62-
//| and UVC will be disabled"""
79+
//| for Python objects. If the allocation fails, a MemoryError is raised.
80+
//| This message can be seen in ``boot_out.txt``."""
6381
//|
6482

65-
STATIC mp_obj_t uvc_enable_framebuffer(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
83+
STATIC mp_obj_t usb_video_enable_framebuffer(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
6684
enum { ARG_width, ARG_height };
6785
static const mp_arg_t allowed_args[] = {
6886
{ MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } },
@@ -74,43 +92,25 @@ STATIC mp_obj_t uvc_enable_framebuffer(size_t n_args, const mp_obj_t *pos_args,
7492
// (but note that most devices will not be able to allocate this much memory.
7593
uint32_t width = mp_arg_validate_int_range(args[ARG_width].u_int, 0, 32767, MP_QSTR_width);
7694
uint32_t height = mp_arg_validate_int_range(args[ARG_height].u_int, 0, 32767, MP_QSTR_height);
77-
if (!shared_module_uvc_enable(width, height)) {
78-
mp_raise_RuntimeError(MP_ERROR_TEXT("Cannot change USB devices now"));
79-
}
80-
81-
return mp_const_none;
82-
};
83-
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(uvc_enable_framebuffer_obj, 0, uvc_enable_framebuffer);
84-
85-
//|
86-
//| def disable() -> None:
87-
//| """Disable the UVC gadget
88-
//|
89-
//| During ``boot.py``, this function may be used to enable the UVC gadget.
90-
//|
91-
//| This function is provided for completeness. The default state of UVC is disabled."""
92-
//|
93-
STATIC mp_obj_t uvc_disable(void) {
94-
if (!shared_module_uvc_disable()) {
95+
if (!shared_module_usb_video_enable(width, height)) {
9596
mp_raise_RuntimeError(MP_ERROR_TEXT("Cannot change USB devices now"));
9697
}
9798

9899
return mp_const_none;
99100
};
100-
STATIC MP_DEFINE_CONST_FUN_OBJ_0(uvc_disable_obj, uvc_disable);
101+
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(usb_video_enable_framebuffer_obj, 0, usb_video_enable_framebuffer);
101102

102-
static const mp_rom_map_elem_t uvc_module_globals_table[] = {
103-
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uvc) },
104-
{ MP_ROM_QSTR(MP_QSTR_UVCFramebuffer), MP_ROM_PTR(&uvc_UVCFramebuffer_type) },
105-
{ MP_ROM_QSTR(MP_QSTR_disable), MP_ROM_PTR(&uvc_disable_obj) },
106-
{ MP_ROM_QSTR(MP_QSTR_enable_framebuffer), MP_ROM_PTR(&uvc_enable_framebuffer_obj) },
103+
static const mp_rom_map_elem_t usb_video_module_globals_table[] = {
104+
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usb_video) },
105+
{ MP_ROM_QSTR(MP_QSTR_USBFramebuffer), MP_ROM_PTR(&usb_video_USBFramebuffer_type) },
106+
{ MP_ROM_QSTR(MP_QSTR_enable_framebuffer), MP_ROM_PTR(&usb_video_enable_framebuffer_obj) },
107107
};
108108

109-
static MP_DEFINE_CONST_DICT(uvc_module_globals, uvc_module_globals_table);
109+
static MP_DEFINE_CONST_DICT(usb_video_module_globals, usb_video_module_globals_table);
110110

111-
const mp_obj_module_t uvc_module = {
111+
const mp_obj_module_t usb_video_module = {
112112
.base = { &mp_type_module },
113-
.globals = (mp_obj_dict_t *)&uvc_module_globals,
113+
.globals = (mp_obj_dict_t *)&usb_video_module_globals,
114114
};
115115

116-
MP_REGISTER_MODULE(MP_QSTR_uvc, uvc_module);
116+
MP_REGISTER_MODULE(MP_QSTR_usb_video, usb_video_module);

shared-bindings/uvc/__init__.h renamed to shared-bindings/usb_video/__init__.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@
2727
#pragma once
2828

2929
#include "shared-module/displayio/Bitmap.h"
30-
bool shared_module_uvc_enable(mp_int_t frame_width, mp_int_t frame_height);
31-
bool shared_module_uvc_disable(void);
32-
void shared_module_uvc_swapbuffers(void);
30+
bool shared_module_usb_video_enable(mp_int_t frame_width, mp_int_t frame_height);
31+
bool shared_module_usb_video_disable(void);
32+
void shared_module_usb_video_swapbuffers(void);

0 commit comments

Comments
 (0)