Skip to content

Commit 488dca5

Browse files
authored
Merge pull request #7922 from tannewt/dvi320
Take in framebuffer resolution, not output res
2 parents 80e1418 + 0aa71ed commit 488dca5

File tree

3 files changed

+37
-33
lines changed

3 files changed

+37
-33
lines changed

ports/raspberrypi/bindings/picodvi/Framebuffer.c

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@
3636
#include "shared-module/framebufferio/FramebufferDisplay.h"
3737

3838
//| class Framebuffer:
39-
//| """A PicoDVI managed frame buffer."""
40-
//|
4139
//| def __init__(
4240
//| self,
4341
//| width: int,
@@ -53,36 +51,37 @@
5351
//| blue_dn: microcontroller.Pin,
5452
//| color_depth: int = 8,
5553
//| ) -> None:
56-
//| """Create a Framebuffer object with the given dimensions (640x480 or 800x480). Memory is
57-
//| allocated outside of onto the heap and then moved outside on VM
58-
//| end.
54+
//| """Create a Framebuffer object with the given dimensions. Memory is
55+
//| allocated outside of onto the heap and then moved outside on VM end.
56+
//|
57+
//| .. warning:: This will change the system clock speed to match the DVI signal.
58+
//| Make sure to initialize other objects after this one so they account
59+
//| for the changed clock.
5960
//|
60-
//| This will change the system clock speed to match the DVI signal.
61-
//| Make sure to initialize other objects after this one so they account
62-
//| for the changed clock. This also allocates a very large framebuffer
63-
//| and is most likely to succeed the earlier it is attempted.
61+
//| This allocates a very large framebuffer and is most likely to succeed
62+
//| the earlier it is attempted.
6463
//|
6564
//| Each dp and dn pair of pins must be neighboring, such as 19 and 20.
6665
//| They must also be ordered the same way. In other words, dp must be
6766
//| less than dn for all pairs or dp must be greater than dn for all pairs.
6867
//|
6968
//| The framebuffer pixel format varies depending on color_depth:
69+
//|
7070
//| * 1 - Each bit is a pixel. Either white (1) or black (0).
7171
//| * 2 - Each 2 bits is a pixels. Grayscale between white (0x3) and black (0x0).
7272
//| * 8 - Each byte is a pixels in RGB332 format.
7373
//| * 16 - Each two bytes are a pixel in RGB565 format.
7474
//|
75-
//| Monochrome framebuffers (color_depth=1 or 2) will be full resolution.
76-
//| Color framebuffers will be half resolution and pixels will be
77-
//| duplicated to create a signal with the target dimensions.
75+
//| Two output resolutions are currently supported, 640x480 and 800x480.
76+
//| Monochrome framebuffers (color_depth=1 or 2) must be full resolution.
77+
//| Color framebuffers must be half resolution (320x240 or 400x240) and
78+
//| pixels will be duplicated to create the signal.
7879
//|
7980
//| A Framebuffer is often used in conjunction with a
8081
//| `framebufferio.FramebufferDisplay`.
8182
//|
82-
//| :param int width: the width of the target display signal. It will be halved when
83-
//| color_depth >= 8 when creating the framebuffer. Only 640 or 800 is currently supported.
84-
//| :param int height: the height of the target display signal. It will be halved when
85-
//| color_depth >= 8 when creating the framebuffer. Only 480 is currently supported.
83+
//| :param int width: the width of the target display signal. Only 320, 400, 640 or 800 is currently supported depending on color_depth.
84+
//| :param int height: the height of the target display signal. Only 240 or 480 is currently supported depending on color_depth.
8685
//| :param ~microcontroller.Pin clk_dp: the positive clock signal pin
8786
//| :param ~microcontroller.Pin clk_dn: the negative clock signal pin
8887
//| :param ~microcontroller.Pin red_dp: the positive red signal pin
@@ -160,8 +159,7 @@ static void check_for_deinit(picodvi_framebuffer_obj_t *self) {
160159
}
161160

162161
//| width: int
163-
//| """The width of the framebuffer, in pixels. It may be doubled for output (and half of what
164-
//| width was given to __init__.)"""
162+
//| """The width of the framebuffer, in pixels. It may be doubled for output."""
165163
STATIC mp_obj_t picodvi_framebuffer_get_width(mp_obj_t self_in) {
166164
picodvi_framebuffer_obj_t *self = (picodvi_framebuffer_obj_t *)self_in;
167165
check_for_deinit(self);
@@ -172,8 +170,7 @@ MP_PROPERTY_GETTER(picodvi_framebuffer_width_obj,
172170
(mp_obj_t)&picodvi_framebuffer_get_width_obj);
173171

174172
//| height: int
175-
//| """The width of the framebuffer, in pixels. It may be doubled for output (and half of what
176-
//| width was given to __init__.)"""
173+
//| """The width of the framebuffer, in pixels. It may be doubled for output."""
177174
//|
178175
STATIC mp_obj_t picodvi_framebuffer_get_height(mp_obj_t self_in) {
179176
picodvi_framebuffer_obj_t *self = (picodvi_framebuffer_obj_t *)self_in;

ports/raspberrypi/boards/adafruit_feather_rp2040_dvi/board.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
void board_init(void) {
3434
picodvi_framebuffer_obj_t *fb = &allocate_display_bus()->picodvi;
3535
fb->base.type = &picodvi_framebuffer_type;
36-
common_hal_picodvi_framebuffer_construct(fb, 640, 480,
36+
common_hal_picodvi_framebuffer_construct(fb, 320, 240,
3737
&pin_GPIO17, &pin_GPIO16,
3838
&pin_GPIO19, &pin_GPIO18,
3939
&pin_GPIO21, &pin_GPIO20,

ports/raspberrypi/common-hal/picodvi/Framebuffer.c

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -138,21 +138,29 @@ void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self,
138138
const mcu_pin_obj_t *green_dp, const mcu_pin_obj_t *green_dn,
139139
const mcu_pin_obj_t *blue_dp, const mcu_pin_obj_t *blue_dn,
140140
mp_uint_t color_depth) {
141+
if (active_picodvi != NULL) {
142+
mp_raise_msg_varg(&mp_type_RuntimeError, translate("%q in use"), MP_QSTR_picodvi);
143+
}
141144

145+
bool color_framebuffer = color_depth >= 8;
142146
const struct dvi_timing *timing = NULL;
143-
if (width == 640 && height == 480) {
147+
if ((width == 640 && height == 480) ||
148+
(width == 320 && height == 240)) {
144149
timing = &dvi_timing_640x480p_60hz;
145-
} else if (width == 800 && height == 480) {
150+
} else if ((width == 800 && height == 480) ||
151+
(width == 400 && height == 240)) {
146152
timing = &dvi_timing_800x480p_60hz;
147153
} else {
148-
if (height == 480) {
149-
mp_raise_ValueError_varg(translate("%q must be %d"), MP_QSTR_width, 480);
154+
if (height != 480 && height != 240) {
155+
mp_raise_ValueError_varg(translate("Invalid %q"), MP_QSTR_height);
150156
}
151-
mp_raise_ValueError_varg(translate("Invalid %q"), MP_QSTR_height);
157+
mp_raise_ValueError_varg(translate("Invalid %q"), MP_QSTR_width);
152158
}
153159

154-
if (active_picodvi != NULL) {
155-
mp_raise_msg_varg(&mp_type_RuntimeError, translate("%q in use"), MP_QSTR_picodvi);
160+
// If the width is > 400, then it must not be color frame buffer and vice
161+
// versa.
162+
if ((width > 400) == color_framebuffer) {
163+
mp_raise_ValueError_varg(translate("Invalid %q"), MP_QSTR_color_depth);
156164
}
157165

158166
bool invert_diffpairs = clk_dn->number < clk_dp->number;
@@ -214,12 +222,12 @@ void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self,
214222
self->height = height;
215223

216224
size_t tmds_bufs_per_scanline;
217-
if (color_depth >= 8) {
225+
size_t scanline_width = width;
226+
if (color_framebuffer) {
218227
dvi_vertical_repeat = 2;
219228
dvi_monochrome_tmds = false;
220-
self->width /= 2;
221-
self->height /= 2;
222229
tmds_bufs_per_scanline = 3;
230+
scanline_width *= 2;
223231
} else {
224232
dvi_vertical_repeat = 1;
225233
dvi_monochrome_tmds = true;
@@ -233,8 +241,7 @@ void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self,
233241
}
234242
self->pitch /= sizeof(uint32_t);
235243
size_t framebuffer_size = self->pitch * self->height;
236-
// use width here because it hasn't been downsized for the frame buffer
237-
self->tmdsbuf_size = tmds_bufs_per_scanline * width / DVI_SYMBOLS_PER_WORD + 1;
244+
self->tmdsbuf_size = tmds_bufs_per_scanline * scanline_width / DVI_SYMBOLS_PER_WORD + 1;
238245
size_t total_allocation_size = sizeof(uint32_t) * (framebuffer_size + DVI_N_TMDS_BUFFERS * self->tmdsbuf_size);
239246
self->allocation = allocate_memory(total_allocation_size, false, true);
240247
if (self->allocation == NULL) {

0 commit comments

Comments
 (0)