Skip to content

Commit 80a1d1a

Browse files
committed
Add support for a non-displayed left portion of screen
1 parent 1ef4e3c commit 80a1d1a

File tree

4 files changed

+49
-10
lines changed

4 files changed

+49
-10
lines changed

ports/espressif/common-hal/dotclockframebuffer/DotClockFramebuffer.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ void common_hal_dotclockframebuffer_framebuffer_construct(dotclockframebuffer_fr
126126
int frequency, int width, int height,
127127
int hsync_pulse_width, int hsync_back_porch, int hsync_front_porch, bool hsync_idle_low,
128128
int vsync_pulse_width, int vsync_back_porch, int vsync_front_porch, bool vsync_idle_low,
129-
bool de_idle_high, bool pclk_active_high, bool pclk_idle_high) {
129+
bool de_idle_high, bool pclk_active_high, bool pclk_idle_high, int overscan_left) {
130130

131131
if (num_red != 5 || num_green != 6 || num_blue != 5) {
132132
mp_raise_ValueError(translate("Must provide 5/6/5 RGB pins"));
@@ -149,7 +149,7 @@ void common_hal_dotclockframebuffer_framebuffer_construct(dotclockframebuffer_fr
149149

150150
esp_lcd_rgb_panel_config_t *cfg = &self->panel_config;
151151
cfg->timings.pclk_hz = frequency;
152-
cfg->timings.h_res = width;
152+
cfg->timings.h_res = width + overscan_left;
153153
cfg->timings.v_res = height;
154154
cfg->timings.hsync_pulse_width = hsync_pulse_width;
155155
cfg->timings.hsync_back_porch = hsync_back_porch;
@@ -206,14 +206,12 @@ void common_hal_dotclockframebuffer_framebuffer_construct(dotclockframebuffer_fr
206206
esp_rgb_panel_t *_rgb_panel = __containerof(self->panel_handle, esp_rgb_panel_t, base);
207207

208208
self->frequency = frequency;
209+
self->row_stride = 2 * (width + overscan_left);
209210
self->refresh_rate = frequency / (width + hsync_front_porch + hsync_back_porch) / (height + vsync_front_porch + vsync_back_porch);
210-
self->bufinfo.buf = _rgb_panel->fb;
211-
self->bufinfo.len = 2 * width * height;
211+
self->bufinfo.buf = (uint8_t *)_rgb_panel->fb + 2 * overscan_left; // first line starts ater overscan_left pixels
212+
self->bufinfo.len = 2 * (cfg->timings.h_res * cfg->timings.v_res - overscan_left); // no overscan after last line
212213
self->bufinfo.typecode = 'H' | MP_OBJ_ARRAY_TYPECODE_FLAG_RW;
213214

214-
memset(self->bufinfo.buf, 0xaa, width * height);
215-
memset(self->bufinfo.buf + width * height, 0x55, width * height);
216-
217215
// LCD_CAM.lcd_ctrl2.lcd_vsync_idle_pol = _vsync_polarity;
218216
// LCD_CAM.lcd_ctrl2.lcd_hsync_idle_pol = _hsync_polarity;
219217

@@ -247,6 +245,10 @@ mp_int_t common_hal_dotclockframebuffer_framebuffer_get_frequency(dotclockframeb
247245
return self->frequency;
248246
}
249247

248+
mp_int_t common_hal_dotclockframebuffer_framebuffer_get_row_stride(dotclockframebuffer_framebuffer_obj_t *self) {
249+
return self->row_stride;
250+
}
251+
250252
void common_hal_dotclockframebuffer_framebuffer_refresh(dotclockframebuffer_framebuffer_obj_t *self) {
251253
Cache_WriteBack_Addr((uint32_t)(self->bufinfo.buf), self->bufinfo.len);
252254
}

ports/espressif/common-hal/dotclockframebuffer/DotClockFramebuffer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
typedef struct dotclockframebuffer_framebuffer_obj {
3838
mp_obj_base_t base;
3939
mp_buffer_info_t bufinfo;
40+
mp_int_t row_stride;
4041
uint32_t frequency, refresh_rate;
4142
uint64_t used_pins_mask;
4243
volatile int32_t frame_count;

shared-bindings/dotclockframebuffer/DotClockFramebuffer.c

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
//| de_idle_high: bool,
6363
//| pclk_active_high: bool,
6464
//| pclk_idle_high: bool,
65+
//| overscan_left: int = 0,
6566
//| ) -> None:
6667
//| """Create a DotClockFramebuffer object associated with the given pins.
6768
//|
@@ -105,14 +106,20 @@
105106
//| :param bool de_idle_high: True if the de signal is high in IDLE state
106107
//| :param bool pclk_active_high: True if the display data is clocked out at the rising edge of dclk
107108
//| :param bool pclk_idle_high: True if the dclk stays at high level in IDLE phase
109+
//|
110+
//| :param int overscan_left: Allocate additional non-visible columns left of the first display column
108111
//| """
112+
//| #:param int overscan_top: Allocate additional non-visible rows above the first display row
113+
//| #:param int overscan_right: Allocate additional non-visible columns right of the last display column
114+
//| #:param int overscan_bottom: Allocate additional non-visible rows below the last display row
109115
//| ...
110116
STATIC mp_obj_t dotclockframebuffer_framebuffer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
111117
enum { ARG_de, ARG_vsync, ARG_hsync, ARG_dclk, ARG_red, ARG_green, ARG_blue,
112118
ARG_frequency, ARG_width, ARG_height,
113119
ARG_hsync_pulse_width, ARG_hsync_back_porch, ARG_hsync_front_porch, ARG_hsync_idle_low,
114120
ARG_vsync_pulse_width, ARG_vsync_back_porch, ARG_vsync_front_porch, ARG_vsync_idle_low,
115-
ARG_de_idle_high, ARG_pclk_active_high, ARG_pclk_idle_high, };
121+
ARG_de_idle_high, ARG_pclk_active_high, ARG_pclk_idle_high,
122+
ARG_overscan_left};
116123

117124
static const mp_arg_t allowed_args[] = {
118125
{ MP_QSTR_de, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED, {.u_obj = mp_const_none } },
@@ -140,6 +147,8 @@ STATIC mp_obj_t dotclockframebuffer_framebuffer_make_new(const mp_obj_type_t *ty
140147
{ MP_QSTR_de_idle_high, MP_ARG_BOOL | MP_ARG_KW_ONLY | MP_ARG_REQUIRED, {.u_bool = false } },
141148
{ MP_QSTR_pclk_active_high, MP_ARG_BOOL | MP_ARG_KW_ONLY | MP_ARG_REQUIRED, {.u_bool = false } },
142149
{ MP_QSTR_pclk_idle_high, MP_ARG_BOOL | MP_ARG_KW_ONLY | MP_ARG_REQUIRED, {.u_bool = false } },
150+
151+
{ MP_QSTR_overscan_left, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0 } },
143152
};
144153

145154
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
@@ -169,7 +178,8 @@ STATIC mp_obj_t dotclockframebuffer_framebuffer_make_new(const mp_obj_type_t *ty
169178
args[ARG_vsync_pulse_width].u_int, args[ARG_vsync_back_porch].u_int, args[ARG_vsync_front_porch].u_int, args[ARG_vsync_idle_low].u_bool,
170179
args[ARG_de_idle_high].u_bool,
171180
args[ARG_pclk_active_high].u_bool,
172-
args[ARG_pclk_idle_high].u_bool
181+
args[ARG_pclk_idle_high].u_bool,
182+
args[ARG_overscan_left].u_int
173183
);
174184

175185
return self;
@@ -243,6 +253,24 @@ MP_DEFINE_CONST_FUN_OBJ_1(dotclockframebuffer_framebuffer_get_height_obj, dotclo
243253
MP_PROPERTY_GETTER(dotclockframebuffer_framebuffer_height_obj,
244254
(mp_obj_t)&dotclockframebuffer_framebuffer_get_height_obj);
245255

256+
//| row_stride: int
257+
//| """The row_stride of the display, in bytes
258+
//|
259+
//| Due to overscan or alignment requirements, the memory address for row N+1 may not be exactly ``2*width`` bytes after the memory address for row N.
260+
//| This property gives the stride in **bytes**.
261+
//|
262+
//| On Espressif this value is **guaranteed** to be a multiple of the 2 (i.e., it is a whole number of pixels)"""
263+
//|
264+
STATIC mp_obj_t dotclockframebuffer_framebuffer_get_row_stride(mp_obj_t self_in) {
265+
dotclockframebuffer_framebuffer_obj_t *self = (dotclockframebuffer_framebuffer_obj_t *)self_in;
266+
check_for_deinit(self);
267+
return MP_OBJ_NEW_SMALL_INT(common_hal_dotclockframebuffer_framebuffer_get_row_stride(self));
268+
}
269+
MP_DEFINE_CONST_FUN_OBJ_1(dotclockframebuffer_framebuffer_get_row_stride_obj, dotclockframebuffer_framebuffer_get_row_stride);
270+
271+
MP_PROPERTY_GETTER(dotclockframebuffer_framebuffer_row_stride_obj,
272+
(mp_obj_t)&dotclockframebuffer_framebuffer_get_row_stride_obj);
273+
246274
STATIC mp_int_t dotclockframebuffer_framebuffer_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
247275
dotclockframebuffer_framebuffer_obj_t *self = (dotclockframebuffer_framebuffer_obj_t *)self_in;
248276
// a readonly framebuffer would be unusual but not impossible
@@ -300,6 +328,10 @@ STATIC void dotclockframebuffer_framebuffer_get_bufinfo(mp_obj_t self_in, mp_buf
300328
*bufinfo = self->bufinfo;
301329
}
302330

331+
STATIC int dotclockframebuffer_framebuffer_get_row_stride_proto(mp_obj_t self_in) {
332+
dotclockframebuffer_framebuffer_obj_t *self = (dotclockframebuffer_framebuffer_obj_t *)self_in;
333+
return common_hal_dotclockframebuffer_framebuffer_get_row_stride(self);
334+
}
303335

304336
STATIC const framebuffer_p_t dotclockframebuffer_framebuffer_proto = {
305337
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuffer)
@@ -309,6 +341,7 @@ STATIC const framebuffer_p_t dotclockframebuffer_framebuffer_proto = {
309341
.get_width = dotclockframebuffer_framebuffer_get_width_proto,
310342
.get_height = dotclockframebuffer_framebuffer_get_height_proto,
311343
.get_color_depth = dotclockframebuffer_framebuffer_get_color_depth_proto,
344+
.get_row_stride = dotclockframebuffer_framebuffer_get_row_stride_proto,
312345
.get_bytes_per_cell = dotclockframebuffer_framebuffer_get_bytes_per_cell_proto,
313346
.get_native_frames_per_second = dotclockframebuffer_framebuffer_get_native_frames_per_second_proto,
314347
.swapbuffers = dotclockframebuffer_framebuffer_swapbuffers,
@@ -319,6 +352,7 @@ STATIC const framebuffer_p_t dotclockframebuffer_framebuffer_proto = {
319352
STATIC const mp_rom_map_elem_t dotclockframebuffer_framebuffer_locals_dict_table[] = {
320353
{ MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&dotclockframebuffer_framebuffer_width_obj) },
321354
{ MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&dotclockframebuffer_framebuffer_height_obj) },
355+
{ MP_ROM_QSTR(MP_QSTR_row_stride), MP_ROM_PTR(&dotclockframebuffer_framebuffer_row_stride_obj) },
322356
{ MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&dotclockframebuffer_framebuffer_frequency_obj) },
323357
{ MP_ROM_QSTR(MP_QSTR_refresh_rate), MP_ROM_PTR(&dotclockframebuffer_framebuffer_refresh_rate_obj) },
324358
{ MP_ROM_QSTR(MP_QSTR_refresh), MP_ROM_PTR(&dotclockframebuffer_framebuffer_refresh_obj) },

shared-bindings/dotclockframebuffer/DotClockFramebuffer.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ void common_hal_dotclockframebuffer_framebuffer_construct(dotclockframebuffer_fr
4545
int frequency, int width, int height,
4646
int hsync_pulse_width, int hsync_back_porch, int hsync_front_porch, bool hsync_idle_low,
4747
int vsync_pulse_width, int vsync_back_porch, int vsync_front_porch, bool vsync_idle_low,
48-
bool de_idle_high, bool pclk_active_high, bool pclk_idle_high);
48+
bool de_idle_high, bool pclk_active_high, bool pclk_idle_high,
49+
int overscan_left);
4950

5051
void common_hal_dotclockframebuffer_framebuffer_deinit(dotclockframebuffer_framebuffer_obj_t *self);
5152
bool common_hal_dotclockframebuffer_framebuffer_deinitialized(dotclockframebuffer_framebuffer_obj_t *self);
@@ -54,4 +55,5 @@ mp_int_t common_hal_dotclockframebuffer_framebuffer_get_width(dotclockframebuffe
5455
mp_int_t common_hal_dotclockframebuffer_framebuffer_get_height(dotclockframebuffer_framebuffer_obj_t *self);
5556
mp_int_t common_hal_dotclockframebuffer_framebuffer_get_frequency(dotclockframebuffer_framebuffer_obj_t *self);
5657
mp_int_t common_hal_dotclockframebuffer_framebuffer_get_refresh_rate(dotclockframebuffer_framebuffer_obj_t *self);
58+
mp_int_t common_hal_dotclockframebuffer_framebuffer_get_row_stride(dotclockframebuffer_framebuffer_obj_t *self);
5759
void common_hal_dotclockframebuffer_framebuffer_refresh(dotclockframebuffer_framebuffer_obj_t *self);

0 commit comments

Comments
 (0)