mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
ports/stm32: Enable DSI display support.
This commit is contained in:
parent
6c63368297
commit
55dfec4f06
@ -376,6 +376,15 @@ void SystemClock_Config(void)
|
|||||||
PeriphClkInitStruct.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PLL2;
|
PeriphClkInitStruct.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PLL2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(DSI)
|
||||||
|
PeriphClkInitStruct.PeriphClockSelection |= RCC_PERIPHCLK_DSI;
|
||||||
|
#if defined(OMV_OSC_DSI_CLKSOURCE)
|
||||||
|
PeriphClkInitStruct.DsiClockSelection = OMV_OSC_DSI_CLKSOURCE;
|
||||||
|
#else
|
||||||
|
PeriphClkInitStruct.DsiClockSelection = RCC_DSICLKSOURCE_PHY;
|
||||||
|
#endif // defined(OMV_OSC_DSI_CLKSOURCE)
|
||||||
|
#endif // defined(DSI)
|
||||||
|
|
||||||
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
|
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
|
||||||
// Initialization Error
|
// Initialization Error
|
||||||
__fatal_error("HAL_RCCEx_PeriphCLKConfig");
|
__fatal_error("HAL_RCCEx_PeriphCLKConfig");
|
||||||
|
|||||||
@ -11,6 +11,7 @@ stm32h7xx_hal_adc.c\
|
|||||||
stm32h7xx_hal_adc_ex.c\
|
stm32h7xx_hal_adc_ex.c\
|
||||||
stm32h7xx_hal_dac.c\
|
stm32h7xx_hal_dac.c\
|
||||||
stm32h7xx_hal_dac_ex.c\
|
stm32h7xx_hal_dac_ex.c\
|
||||||
|
stm32h7xx_hal_dsi.c\
|
||||||
stm32h7xx_hal.c\
|
stm32h7xx_hal.c\
|
||||||
stm32h7xx_hal_cortex.c\
|
stm32h7xx_hal_cortex.c\
|
||||||
stm32h7xx_hal_crc.c\
|
stm32h7xx_hal_crc.c\
|
||||||
|
|||||||
@ -185,6 +185,72 @@ STATIC mp_obj_t py_display_write(uint n_args, const mp_obj_t *args, mp_map_t *kw
|
|||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_display_write_obj, 2, py_display_write);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_display_write_obj, 2, py_display_write);
|
||||||
|
|
||||||
|
#ifdef OMV_DSI_DISPLAY_CONTROLLER
|
||||||
|
STATIC mp_obj_t py_display_dsi_write(uint n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||||
|
enum { ARG_cmd, ARG_args, ARG_dcs };
|
||||||
|
static const mp_arg_t allowed_args[] = {
|
||||||
|
{ MP_QSTR_cmd, MP_ARG_INT | MP_ARG_REQUIRED },
|
||||||
|
{ MP_QSTR_args, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||||
|
{ MP_QSTR_dcs, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_bool = false } },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parse args.
|
||||||
|
py_display_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||||
|
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||||
|
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||||
|
|
||||||
|
py_display_p_t *display_p = (py_display_p_t *) MP_OBJ_TYPE_GET_SLOT(self->base.type, protocol);
|
||||||
|
if (display_p->dsi_write == NULL) {
|
||||||
|
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Expected a DSI display controller"));
|
||||||
|
} else if (args[ARG_args].u_obj == mp_const_none) {
|
||||||
|
display_p->dsi_write(self, args[ARG_cmd].u_int, NULL, 0, args[ARG_dcs].u_bool);
|
||||||
|
} else if (mp_obj_is_int(args[ARG_args].u_obj)) {
|
||||||
|
uint8_t arg = mp_obj_get_int(args[ARG_args].u_obj);
|
||||||
|
display_p->dsi_write(self, args[ARG_cmd].u_int, &arg, 1, args[ARG_dcs].u_bool);
|
||||||
|
} else {
|
||||||
|
mp_buffer_info_t rbuf;
|
||||||
|
mp_get_buffer_raise(args[ARG_args].u_obj, &rbuf, MP_BUFFER_READ);
|
||||||
|
display_p->dsi_write(self, args[ARG_cmd].u_int, rbuf.buf, rbuf.len, args[ARG_dcs].u_bool);
|
||||||
|
}
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_display_dsi_write_obj, 1, py_display_dsi_write);
|
||||||
|
|
||||||
|
STATIC mp_obj_t py_display_dsi_read(uint n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||||
|
enum { ARG_cmd, ARG_len, ARG_args, ARG_dcs };
|
||||||
|
static const mp_arg_t allowed_args[] = {
|
||||||
|
{ MP_QSTR_cmd, MP_ARG_INT | MP_ARG_REQUIRED },
|
||||||
|
{ MP_QSTR_len, MP_ARG_INT | MP_ARG_REQUIRED },
|
||||||
|
{ MP_QSTR_args, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||||
|
{ MP_QSTR_dcs, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_bool = false } },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parse args.
|
||||||
|
py_display_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||||
|
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||||
|
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||||
|
|
||||||
|
py_display_p_t *display_p = (py_display_p_t *) MP_OBJ_TYPE_GET_SLOT(self->base.type, protocol);
|
||||||
|
mp_obj_array_t *wbuf = MP_OBJ_TO_PTR(mp_obj_new_bytearray_by_ref(args[ARG_len].u_int,
|
||||||
|
m_new(byte, args[ARG_len].u_int)));
|
||||||
|
if (display_p->dsi_read == NULL) {
|
||||||
|
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Expected a DSI display controller"));
|
||||||
|
} else if (args[ARG_args].u_obj == mp_const_none) {
|
||||||
|
display_p->dsi_read(self, args[ARG_cmd].u_int, NULL, 0, wbuf->items, wbuf->len, args[ARG_dcs].u_bool);
|
||||||
|
} else if (mp_obj_is_int(args[ARG_args].u_obj)) {
|
||||||
|
uint8_t arg = mp_obj_get_int(args[ARG_args].u_obj);
|
||||||
|
display_p->dsi_read(self, args[ARG_cmd].u_int, &arg, 1, wbuf->items, wbuf->len, args[ARG_dcs].u_bool);
|
||||||
|
} else {
|
||||||
|
mp_buffer_info_t rbuf;
|
||||||
|
mp_get_buffer_raise(args[ARG_args].u_obj, &rbuf, MP_BUFFER_READ);
|
||||||
|
display_p->dsi_read(self, args[ARG_cmd].u_int, rbuf.buf, rbuf.len,
|
||||||
|
wbuf->items, wbuf->len, args[ARG_dcs].u_bool);
|
||||||
|
}
|
||||||
|
return MP_OBJ_FROM_PTR(wbuf);
|
||||||
|
}
|
||||||
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_display_dsi_read_obj, 1, py_display_dsi_read);
|
||||||
|
#endif
|
||||||
|
|
||||||
STATIC const mp_rom_map_elem_t py_display_locals_dict_table[] = {
|
STATIC const mp_rom_map_elem_t py_display_locals_dict_table[] = {
|
||||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_display) },
|
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_display) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&py_display_deinit_obj) },
|
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&py_display_deinit_obj) },
|
||||||
@ -198,6 +264,10 @@ STATIC const mp_rom_map_elem_t py_display_locals_dict_table[] = {
|
|||||||
{ MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&py_display_clear_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&py_display_clear_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_backlight), MP_ROM_PTR(&py_display_backlight_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_backlight), MP_ROM_PTR(&py_display_backlight_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&py_display_write_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&py_display_write_obj) },
|
||||||
|
#ifdef OMV_DSI_DISPLAY_CONTROLLER
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_dsi_write), MP_ROM_PTR(&py_display_dsi_write_obj) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_dsi_read), MP_ROM_PTR(&py_display_dsi_read_obj) },
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
MP_DEFINE_CONST_DICT(py_display_locals_dict, py_display_locals_dict_table);
|
MP_DEFINE_CONST_DICT(py_display_locals_dict, py_display_locals_dict_table);
|
||||||
|
|
||||||
@ -242,5 +312,9 @@ const mp_obj_module_t display_module = {
|
|||||||
.globals = (mp_obj_t) &globals_dict,
|
.globals = (mp_obj_t) &globals_dict,
|
||||||
};
|
};
|
||||||
|
|
||||||
MP_REGISTER_MODULE(MP_QSTR_display, display_module);
|
#ifdef MP_REGISTER_EXTENSIBLE_MODULE
|
||||||
|
MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_display, display_module);
|
||||||
|
#else
|
||||||
|
MP_REGISTER_MODULE(MP_QSTR_udisplay, display_module);
|
||||||
|
#endif
|
||||||
#endif // MICROPY_PY_DISPLAY
|
#endif // MICROPY_PY_DISPLAY
|
||||||
|
|||||||
@ -41,6 +41,7 @@ typedef enum {
|
|||||||
|
|
||||||
typedef struct _py_display_obj_t {
|
typedef struct _py_display_obj_t {
|
||||||
mp_obj_base_t base;
|
mp_obj_base_t base;
|
||||||
|
uint32_t vcid;
|
||||||
uint32_t width;
|
uint32_t width;
|
||||||
uint32_t height;
|
uint32_t height;
|
||||||
uint32_t framesize;
|
uint32_t framesize;
|
||||||
@ -49,6 +50,7 @@ typedef struct _py_display_obj_t {
|
|||||||
bool bgr;
|
bool bgr;
|
||||||
bool byte_swap;
|
bool byte_swap;
|
||||||
bool display_on;
|
bool display_on;
|
||||||
|
mp_obj_t controller;
|
||||||
#if defined(OMV_SPI_DISPLAY_CONTROLLER)
|
#if defined(OMV_SPI_DISPLAY_CONTROLLER)
|
||||||
omv_spi_t spi_bus;
|
omv_spi_t spi_bus;
|
||||||
bool spi_tx_running;
|
bool spi_tx_running;
|
||||||
@ -68,6 +70,11 @@ typedef struct _py_display_p_t {
|
|||||||
float x_scale, float y_scale, rectangle_t *roi, int rgb_channel, int alpha,
|
float x_scale, float y_scale, rectangle_t *roi, int rgb_channel, int alpha,
|
||||||
const uint16_t *color_palette, const uint8_t *alpha_palette, image_hint_t hint);
|
const uint16_t *color_palette, const uint8_t *alpha_palette, image_hint_t hint);
|
||||||
void (*set_backlight) (py_display_obj_t *self, uint32_t intensity);
|
void (*set_backlight) (py_display_obj_t *self, uint32_t intensity);
|
||||||
|
#ifdef OMV_DSI_DISPLAY_CONTROLLER
|
||||||
|
// To be implemented by MIPI DSI controllers.
|
||||||
|
int (*dsi_write) (py_display_obj_t *self, uint8_t cmd, uint8_t *args, size_t n_args, bool dcs);
|
||||||
|
int (*dsi_read) (py_display_obj_t *self, uint8_t cmd, uint8_t *args, size_t n_args, uint8_t *buf, size_t len, bool dcs);
|
||||||
|
#endif
|
||||||
} py_display_p_t;
|
} py_display_p_t;
|
||||||
|
|
||||||
extern const mp_obj_type_t py_spi_display_type;
|
extern const mp_obj_type_t py_spi_display_type;
|
||||||
|
|||||||
@ -6,11 +6,13 @@
|
|||||||
*
|
*
|
||||||
* This work is licensed under the MIT license, see the file LICENSE for details.
|
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||||
*
|
*
|
||||||
* LTDC display Python module.
|
* LTDC/DSI display Python module.
|
||||||
*/
|
*/
|
||||||
#include "omv_boardconfig.h"
|
#include "omv_boardconfig.h"
|
||||||
|
|
||||||
#if MICROPY_PY_DISPLAY && defined(OMV_RGB_DISPLAY_CONTROLLER)
|
#if MICROPY_PY_DISPLAY && \
|
||||||
|
(defined(OMV_RGB_DISPLAY_CONTROLLER) || \
|
||||||
|
defined(OMV_DSI_DISPLAY_CONTROLLER))
|
||||||
|
|
||||||
#include "py/obj.h"
|
#include "py/obj.h"
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
@ -21,11 +23,15 @@
|
|||||||
#include "omv_gpio.h"
|
#include "omv_gpio.h"
|
||||||
#include "py_display.h"
|
#include "py_display.h"
|
||||||
|
|
||||||
#if defined(OMV_RGB_DISPLAY_BL_PIN)
|
#if defined(OMV_DSI_DISPLAY_BL_PIN)
|
||||||
|
#define OMV_DISPLAY_BL_PIN OMV_DSI_DISPLAY_BL_PIN
|
||||||
|
#elif defined(OMV_RGB_DISPLAY_BL_PIN)
|
||||||
#define OMV_DISPLAY_BL_PIN OMV_RGB_DISPLAY_BL_PIN
|
#define OMV_DISPLAY_BL_PIN OMV_RGB_DISPLAY_BL_PIN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(OMV_RGB_DISPLAY_DISP_PIN)
|
#if defined(OMV_DSI_DISPLAY_DISP_PIN)
|
||||||
|
#define OMV_DISPLAY_DISP_PIN OMV_DSI_DISPLAY_DISP_PIN
|
||||||
|
#elif defined(OMV_RGB_DISPLAY_DISP_PIN)
|
||||||
#define OMV_DISPLAY_DISP_PIN OMV_RGB_DISPLAY_DISP_PIN
|
#define OMV_DISPLAY_DISP_PIN OMV_RGB_DISPLAY_DISP_PIN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -46,6 +52,9 @@ typedef struct display_mode {
|
|||||||
typedef struct _display_state {
|
typedef struct _display_state {
|
||||||
py_display_obj_t *self;
|
py_display_obj_t *self;
|
||||||
LTDC_HandleTypeDef hltdc;
|
LTDC_HandleTypeDef hltdc;
|
||||||
|
#ifdef OMV_DSI_DISPLAY_CONTROLLER
|
||||||
|
DSI_HandleTypeDef hdsi;
|
||||||
|
#endif
|
||||||
#ifdef OMV_DISPLAY_BL_TIM
|
#ifdef OMV_DISPLAY_BL_TIM
|
||||||
TIM_HandleTypeDef htim;
|
TIM_HandleTypeDef htim;
|
||||||
#endif
|
#endif
|
||||||
@ -56,94 +65,94 @@ static display_state_t display;
|
|||||||
|
|
||||||
static const display_mode_t display_modes[] = {
|
static const display_mode_t display_modes[] = {
|
||||||
{ // QVGA
|
{ // QVGA
|
||||||
.hactive=320, .vactive=240, .pixel_clock=6144,
|
.hactive = 320, .vactive = 240, .pixel_clock = 6144,
|
||||||
.hsync_len=32, .hback_porch=40, .hfront_porch=8,
|
.hsync_len = 32, .hback_porch = 40, .hfront_porch = 8,
|
||||||
.vsync_len=8, .vback_porch=6, .vfront_porch=1
|
.vsync_len = 8, .vback_porch = 6, .vfront_porch = 1
|
||||||
},
|
},
|
||||||
{ // TQVGA
|
{ // TQVGA
|
||||||
.hactive=240, .vactive=320, .pixel_clock=6426,
|
.hactive = 240, .vactive = 320, .pixel_clock = 6426,
|
||||||
.hsync_len=32, .hback_porch=40, .hfront_porch=8,
|
.hsync_len = 32, .hback_porch = 40, .hfront_porch = 8,
|
||||||
.vsync_len=8, .vback_porch=6, .vfront_porch=1
|
.vsync_len = 8, .vback_porch = 6, .vfront_porch = 1
|
||||||
},
|
},
|
||||||
{ // FHVGA
|
{ // FHVGA
|
||||||
.hactive=480, .vactive=272, .pixel_clock=9633,
|
.hactive = 480, .vactive = 272, .pixel_clock = 9633,
|
||||||
.hsync_len=32, .hback_porch=40, .hfront_porch=8,
|
.hsync_len = 32, .hback_porch = 40, .hfront_porch = 8,
|
||||||
.vsync_len=8, .vback_porch=6, .vfront_porch=1
|
.vsync_len = 8, .vback_porch = 6, .vfront_porch = 1
|
||||||
},
|
},
|
||||||
{ // FHVGA2
|
{ // FHVGA2
|
||||||
.hactive=480, .vactive=128, .pixel_clock=4799,
|
.hactive = 480, .vactive = 128, .pixel_clock = 4799,
|
||||||
.hsync_len=32, .hback_porch=40, .hfront_porch=8,
|
.hsync_len = 32, .hback_porch = 40, .hfront_porch = 8,
|
||||||
.vsync_len=8, .vback_porch=6, .vfront_porch=1
|
.vsync_len = 8, .vback_porch = 6, .vfront_porch = 1
|
||||||
},
|
},
|
||||||
{ // VGA
|
{ // VGA
|
||||||
.hactive=640, .vactive=480, .pixel_clock=21363,
|
.hactive = 640, .vactive = 480, .pixel_clock = 21363,
|
||||||
.hsync_len=32, .hback_porch=40, .hfront_porch=8,
|
.hsync_len = 32, .hback_porch = 40, .hfront_porch = 8,
|
||||||
.vsync_len=8, .vback_porch=6, .vfront_porch=1
|
.vsync_len = 8, .vback_porch = 6, .vfront_porch = 1
|
||||||
},
|
},
|
||||||
{ // THVGA
|
{ // THVGA
|
||||||
.hactive=320, .vactive=480, .pixel_clock=11868,
|
.hactive = 320, .vactive = 480, .pixel_clock = 11868,
|
||||||
.hsync_len=32, .hback_porch=40, .hfront_porch=8,
|
.hsync_len = 32, .hback_porch = 40, .hfront_porch = 8,
|
||||||
.vsync_len=8, .vback_porch=6, .vfront_porch=1
|
.vsync_len = 8, .vback_porch = 6, .vfront_porch = 1
|
||||||
},
|
},
|
||||||
{ // FWVGA
|
{ // FWVGA
|
||||||
.hactive=800, .vactive=480, .pixel_clock=26110,
|
.hactive = 800, .vactive = 480, .pixel_clock = 26110,
|
||||||
.hsync_len=32, .hback_porch=40, .hfront_porch=8,
|
.hsync_len = 32, .hback_porch = 40, .hfront_porch = 8,
|
||||||
.vsync_len=8, .vback_porch=6, .vfront_porch=1
|
.vsync_len = 8, .vback_porch = 6, .vfront_porch = 1
|
||||||
},
|
},
|
||||||
{ // FWVGA2
|
{ // FWVGA2
|
||||||
.hactive=800, .vactive=320, .pixel_clock=17670,
|
.hactive = 800, .vactive = 320, .pixel_clock = 17670,
|
||||||
.hsync_len=32, .hback_porch=40, .hfront_porch=8,
|
.hsync_len = 32, .hback_porch = 40, .hfront_porch = 8,
|
||||||
.vsync_len=8, .vback_porch=6, .vfront_porch=1
|
.vsync_len = 8, .vback_porch = 6, .vfront_porch = 1
|
||||||
},
|
},
|
||||||
{ // TFWVGA
|
{ // TFWVGA
|
||||||
.hactive=480, .vactive=800, .pixel_clock=27624,
|
.hactive = 480, .vactive = 800, .pixel_clock = 27624,
|
||||||
.hsync_len=32, .hback_porch=40, .hfront_porch=8,
|
.hsync_len = 32, .hback_porch = 40, .hfront_porch = 8,
|
||||||
.vsync_len=8, .vback_porch=6, .vfront_porch=9
|
.vsync_len = 8, .vback_porch = 6, .vfront_porch = 9
|
||||||
},
|
},
|
||||||
{ // TFWVGA2
|
{ // TFWVGA2
|
||||||
.hactive=480, .vactive=480, .pixel_clock=16615,
|
.hactive = 480, .vactive = 480, .pixel_clock = 16615,
|
||||||
.hsync_len=32, .hback_porch=40, .hfront_porch=8,
|
.hsync_len = 32, .hback_porch = 40, .hfront_porch = 8,
|
||||||
.vsync_len=8, .vback_porch=6, .vfront_porch=1
|
.vsync_len = 8, .vback_porch = 6, .vfront_porch = 1
|
||||||
},
|
},
|
||||||
{ // SVGA
|
{ // SVGA
|
||||||
.hactive=800, .vactive=600, .pixel_clock=32597,
|
.hactive = 800, .vactive = 600, .pixel_clock = 32597,
|
||||||
.hsync_len=32, .hback_porch=40, .hfront_porch=8,
|
.hsync_len = 32, .hback_porch = 40, .hfront_porch = 8,
|
||||||
.vsync_len=8, .vback_porch=6, .vfront_porch=4
|
.vsync_len = 8, .vback_porch = 6, .vfront_porch = 4
|
||||||
},
|
},
|
||||||
{ // WSVGA
|
{ // WSVGA
|
||||||
.hactive=1024, .vactive=600, .pixel_clock=40895,
|
.hactive = 1024, .vactive = 600, .pixel_clock = 40895,
|
||||||
.hsync_len=32, .hback_porch=40, .hfront_porch=8,
|
.hsync_len = 32, .hback_porch = 40, .hfront_porch = 8,
|
||||||
.vsync_len=8, .vback_porch=6, .vfront_porch=4
|
.vsync_len = 8, .vback_porch = 6, .vfront_porch = 4
|
||||||
},
|
},
|
||||||
{ // XGA
|
{ // XGA
|
||||||
.hactive=1024, .vactive=768, .pixel_clock=52277,
|
.hactive = 1024, .vactive = 768, .pixel_clock = 52277,
|
||||||
.hsync_len=32, .hback_porch=40, .hfront_porch=8,
|
.hsync_len = 32, .hback_porch = 40, .hfront_porch = 8,
|
||||||
.vsync_len=8, .vback_porch=6, .vfront_porch=8
|
.vsync_len = 8, .vback_porch = 6, .vfront_porch = 8
|
||||||
},
|
},
|
||||||
{ // SXGA
|
{ // SXGA
|
||||||
.hactive=1280, .vactive=1024, .pixel_clock=85920,
|
.hactive = 1280, .vactive = 1024, .pixel_clock = 85920,
|
||||||
.hsync_len=32, .hback_porch=40, .hfront_porch=8,
|
.hsync_len = 32, .hback_porch = 40, .hfront_porch = 8,
|
||||||
.vsync_len=8, .vback_porch=6, .vfront_porch=16
|
.vsync_len = 8, .vback_porch = 6, .vfront_porch = 16
|
||||||
},
|
},
|
||||||
{ // SXGA2
|
{ // SXGA2
|
||||||
.hactive=1280, .vactive=400, .pixel_clock=33830,
|
.hactive = 1280, .vactive = 400, .pixel_clock = 33830,
|
||||||
.hsync_len=32, .hback_porch=40, .hfront_porch=8,
|
.hsync_len = 32, .hback_porch = 40, .hfront_porch = 8,
|
||||||
.vsync_len=8, .vback_porch=6, .vfront_porch=1
|
.vsync_len = 8, .vback_porch = 6, .vfront_porch = 1
|
||||||
},
|
},
|
||||||
{ // UXGA
|
{ // UXGA
|
||||||
.hactive=1600, .vactive=1200, .pixel_clock=124364,
|
.hactive = 1600, .vactive = 1200, .pixel_clock = 124364,
|
||||||
.hsync_len=32, .hback_porch=40, .hfront_porch=8,
|
.hsync_len = 32, .hback_porch = 40, .hfront_porch = 8,
|
||||||
.vsync_len=8, .vback_porch=6, .vfront_porch=21
|
.vsync_len = 8, .vback_porch = 6, .vfront_porch = 21
|
||||||
},
|
},
|
||||||
{ // HD
|
{ // HD
|
||||||
.hactive=1280, .vactive=720, .pixel_clock=60405,
|
.hactive = 1280, .vactive = 720, .pixel_clock = 60405,
|
||||||
.hsync_len=32, .hback_porch=40, .hfront_porch=8,
|
.hsync_len = 32, .hback_porch = 40, .hfront_porch = 8,
|
||||||
.vsync_len=8, .vback_porch=6, .vfront_porch=7
|
.vsync_len = 8, .vback_porch = 6, .vfront_porch = 7
|
||||||
},
|
},
|
||||||
{ // FHD
|
{ // FHD
|
||||||
.hactive=1920, .vactive=1080, .pixel_clock=133187,
|
.hactive = 1920, .vactive = 1080, .pixel_clock = 133187,
|
||||||
.hsync_len=32, .hback_porch=40, .hfront_porch=8,
|
.hsync_len = 32, .hback_porch = 40, .hfront_porch = 8,
|
||||||
.vsync_len=8, .vback_porch=6, .vfront_porch=17
|
.vsync_len = 8, .vback_porch = 6, .vfront_porch = 17
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -151,6 +160,12 @@ void LTDC_IRQHandler() {
|
|||||||
HAL_LTDC_IRQHandler(&display.hltdc);
|
HAL_LTDC_IRQHandler(&display.hltdc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef OMV_DSI_DISPLAY_CONTROLLER
|
||||||
|
void DSI_IRQHandler(void) {
|
||||||
|
HAL_DSI_IRQHandler(&display.hdsi);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void pll_config(int framesize, int refresh) {
|
static void pll_config(int framesize, int refresh) {
|
||||||
uint32_t pixel_clock = (display_modes[framesize].pixel_clock * refresh) / 60;
|
uint32_t pixel_clock = (display_modes[framesize].pixel_clock * refresh) / 60;
|
||||||
|
|
||||||
@ -209,6 +224,97 @@ static void pll_config(int framesize, int refresh) {
|
|||||||
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Unable to initialize LTDC PLL!"));
|
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Unable to initialize LTDC PLL!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef OMV_DSI_DISPLAY_CONTROLLER
|
||||||
|
static void dsi_init(py_display_obj_t *self) {
|
||||||
|
const display_mode_t *dm = &display_modes[self->framesize];
|
||||||
|
|
||||||
|
DSI_PLLInitTypeDef dsi_pllinit;
|
||||||
|
dsi_pllinit.PLLNDIV = 125;
|
||||||
|
dsi_pllinit.PLLIDF = DSI_PLL_IN_DIV4;
|
||||||
|
dsi_pllinit.PLLODF = DSI_PLL_OUT_DIV1;
|
||||||
|
uint32_t LANE_BYTE_CLOCK = 62500;
|
||||||
|
|
||||||
|
display.hdsi.Instance = DSI;
|
||||||
|
display.hdsi.Init.NumberOfLanes = DSI_TWO_DATA_LANES;
|
||||||
|
display.hdsi.Init.TXEscapeCkdiv = 3;
|
||||||
|
display.hdsi.Init.AutomaticClockLaneControl = DSI_AUTO_CLK_LANE_CTRL_DISABLE;
|
||||||
|
HAL_DSI_Init(&display.hdsi, &dsi_pllinit);
|
||||||
|
|
||||||
|
#if OMV_DSI_DISPLAY_TE_ENABLE
|
||||||
|
DSI_CmdCfgTypeDef dsi_cmd;
|
||||||
|
dsi_cmd.VirtualChannelID = self->vcid;
|
||||||
|
dsi_cmd.HSPolarity = DSI_HSYNC_ACTIVE_LOW;
|
||||||
|
dsi_cmd.VSPolarity = DSI_VSYNC_ACTIVE_LOW;
|
||||||
|
dsi_cmd.DEPolarity = DSI_DATA_ENABLE_ACTIVE_HIGH;
|
||||||
|
dsi_cmd.ColorCoding = DSI_RGB565;
|
||||||
|
dsi_cmd.CommandSize = 0xFFFFU;
|
||||||
|
dsi_cmd.TearingEffectSource = DSI_TE_DSILINK;
|
||||||
|
dsi_cmd.TearingEffectPolarity = DSI_TE_RISING_EDGE;
|
||||||
|
dsi_cmd.VSyncPol = DSI_VSYNC_FALLING;
|
||||||
|
dsi_cmd.AutomaticRefresh = DSI_AR_DISABLE;
|
||||||
|
dsi_cmd.TEAcknowledgeRequest = DSI_TE_ACKNOWLEDGE_ENABLE;
|
||||||
|
HAL_DSI_ConfigAdaptedCommandMode(&display.hdsi, &dsi_cmd);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Configure DSI PHY HS2LP and LP2HS timings
|
||||||
|
DSI_PHY_TimerTypeDef dsi_phyinit;
|
||||||
|
dsi_phyinit.ClockLaneHS2LPTime = 35;
|
||||||
|
dsi_phyinit.ClockLaneLP2HSTime = 35;
|
||||||
|
dsi_phyinit.DataLaneHS2LPTime = 35;
|
||||||
|
dsi_phyinit.DataLaneLP2HSTime = 35;
|
||||||
|
dsi_phyinit.DataLaneMaxReadTime = 0;
|
||||||
|
dsi_phyinit.StopWaitTime = 10;
|
||||||
|
HAL_DSI_ConfigPhyTimer(&display.hdsi, &dsi_phyinit);
|
||||||
|
HAL_DSI_ConfigFlowControl(&display.hdsi, DSI_FLOW_CONTROL_BTA);
|
||||||
|
HAL_DSI_SetLowPowerRXFilter(&display.hdsi, 10000);
|
||||||
|
HAL_DSI_ConfigErrorMonitor(&display.hdsi, HAL_DSI_ERROR_NONE);
|
||||||
|
|
||||||
|
// Timing parameters for Video modes
|
||||||
|
DSI_VidCfgTypeDef dsi_vidcfg = { 0 };
|
||||||
|
dsi_vidcfg.VirtualChannelID = self->vcid;
|
||||||
|
dsi_vidcfg.ColorCoding = DSI_RGB565;
|
||||||
|
dsi_vidcfg.LooselyPacked = DSI_LOOSELY_PACKED_DISABLE;
|
||||||
|
dsi_vidcfg.VSPolarity = DSI_VSYNC_ACTIVE_LOW;
|
||||||
|
dsi_vidcfg.HSPolarity = DSI_HSYNC_ACTIVE_LOW;
|
||||||
|
dsi_vidcfg.DEPolarity = DSI_DATA_ENABLE_ACTIVE_HIGH;
|
||||||
|
dsi_vidcfg.Mode = DSI_VID_MODE_BURST;
|
||||||
|
dsi_vidcfg.NullPacketSize = 0xFFF;
|
||||||
|
dsi_vidcfg.NumberOfChunks = 0;
|
||||||
|
dsi_vidcfg.PacketSize = self->width;
|
||||||
|
dsi_vidcfg.HorizontalSyncActive = dm->hsync_len * LANE_BYTE_CLOCK / dm->pixel_clock;
|
||||||
|
dsi_vidcfg.HorizontalBackPorch = dm->hback_porch * LANE_BYTE_CLOCK / dm->pixel_clock;
|
||||||
|
dsi_vidcfg.HorizontalLine = (self->width + dm->hsync_len + dm->hback_porch + dm->hfront_porch)
|
||||||
|
* LANE_BYTE_CLOCK / dm->pixel_clock;
|
||||||
|
dsi_vidcfg.VerticalSyncActive = dm->vsync_len;
|
||||||
|
dsi_vidcfg.VerticalBackPorch = dm->vback_porch;
|
||||||
|
dsi_vidcfg.VerticalFrontPorch = dm->vfront_porch;
|
||||||
|
dsi_vidcfg.VerticalActive = self->height;
|
||||||
|
|
||||||
|
// Enable/disable sending LP command while streaming
|
||||||
|
dsi_vidcfg.LPCommandEnable = DSI_LP_COMMAND_ENABLE;
|
||||||
|
// Largest packet size possible to transmit in LP mode in VSA, VBP, VFP regions
|
||||||
|
dsi_vidcfg.LPLargestPacketSize = 0;
|
||||||
|
// Largest packet size possible to transmit in LP mode in HFP region during VACT period
|
||||||
|
dsi_vidcfg.LPVACTLargestPacketSize = 0;
|
||||||
|
// Specify for each region, if the going in LP mode is allowed while streaming
|
||||||
|
dsi_vidcfg.LPHorizontalFrontPorchEnable = DSI_LP_HFP_ENABLE;
|
||||||
|
dsi_vidcfg.LPHorizontalBackPorchEnable = DSI_LP_HBP_ENABLE;
|
||||||
|
dsi_vidcfg.LPVerticalActiveEnable = DSI_LP_VACT_ENABLE;
|
||||||
|
dsi_vidcfg.LPVerticalFrontPorchEnable = DSI_LP_VFP_ENABLE;
|
||||||
|
dsi_vidcfg.LPVerticalBackPorchEnable = DSI_LP_VBP_ENABLE;
|
||||||
|
dsi_vidcfg.LPVerticalSyncActiveEnable = DSI_LP_VSYNC_ENABLE;
|
||||||
|
|
||||||
|
// Configure DSI Video mode timings with settings set above
|
||||||
|
HAL_DSI_ConfigVideoMode(&display.hdsi, &dsi_vidcfg);
|
||||||
|
HAL_DSI_Start(&display.hdsi);
|
||||||
|
HAL_DSI_Refresh(&display.hdsi);
|
||||||
|
HAL_DSI_PatternGeneratorStop(&display.hdsi);
|
||||||
|
|
||||||
|
HAL_NVIC_SetPriority(DSI_IRQn, IRQ_PRI_LTDC, 0);
|
||||||
|
HAL_NVIC_EnableIRQ(DSI_IRQn);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void ltdc_init(py_display_obj_t *self) {
|
static void ltdc_init(py_display_obj_t *self) {
|
||||||
const display_mode_t *dm = &display_modes[self->framesize];
|
const display_mode_t *dm = &display_modes[self->framesize];
|
||||||
uint32_t fb_size = self->width * self->height * sizeof(uint16_t);
|
uint32_t fb_size = self->width * self->height * sizeof(uint16_t);
|
||||||
@ -240,12 +346,12 @@ static void ltdc_init(py_display_obj_t *self) {
|
|||||||
display.hltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL,
|
display.hltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL,
|
||||||
display.hltdc.Init.PCPolarity = LTDC_PCPOLARITY_IPC,
|
display.hltdc.Init.PCPolarity = LTDC_PCPOLARITY_IPC,
|
||||||
|
|
||||||
display.hltdc.Init.HorizontalSync = dm->hsync_len -1;
|
display.hltdc.Init.HorizontalSync = dm->hsync_len - 1;
|
||||||
display.hltdc.Init.VerticalSync = dm->vsync_len - 1;
|
display.hltdc.Init.VerticalSync = dm->vsync_len - 1;
|
||||||
display.hltdc.Init.AccumulatedHBP = dm->hsync_len + dm->hback_porch -1;
|
display.hltdc.Init.AccumulatedHBP = dm->hsync_len + dm->hback_porch - 1;
|
||||||
display.hltdc.Init.AccumulatedVBP = dm->vsync_len + dm->vback_porch -1;
|
display.hltdc.Init.AccumulatedVBP = dm->vsync_len + dm->vback_porch - 1;
|
||||||
display.hltdc.Init.AccumulatedActiveW = dm->hsync_len + dm->hback_porch + self->width -1;
|
display.hltdc.Init.AccumulatedActiveW = dm->hsync_len + dm->hback_porch + self->width - 1;
|
||||||
display.hltdc.Init.AccumulatedActiveH = dm->vsync_len + dm->vback_porch + self->height -1;
|
display.hltdc.Init.AccumulatedActiveH = dm->vsync_len + dm->vback_porch + self->height - 1;
|
||||||
display.hltdc.Init.TotalWidth = dm->hsync_len + dm->hback_porch + self->width + dm->hfront_porch - 1;
|
display.hltdc.Init.TotalWidth = dm->hsync_len + dm->hback_porch + self->width + dm->hfront_porch - 1;
|
||||||
display.hltdc.Init.TotalHeigh = dm->vsync_len + dm->vback_porch + self->height + dm->vfront_porch - 1;
|
display.hltdc.Init.TotalHeigh = dm->vsync_len + dm->vback_porch + self->height + dm->vfront_porch - 1;
|
||||||
|
|
||||||
@ -281,8 +387,8 @@ void HAL_LTDC_LineEventCallback(LTDC_HandleTypeDef *hltdc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void display_write(py_display_obj_t *self, image_t *src_img, int dst_x_start, int dst_y_start,
|
static void display_write(py_display_obj_t *self, image_t *src_img, int dst_x_start, int dst_y_start,
|
||||||
float x_scale, float y_scale, rectangle_t *roi, int rgb_channel, int alpha,
|
float x_scale, float y_scale, rectangle_t *roi, int rgb_channel, int alpha,
|
||||||
const uint16_t *color_palette, const uint8_t *alpha_palette, image_hint_t hint) {
|
const uint16_t *color_palette, const uint8_t *alpha_palette, image_hint_t hint) {
|
||||||
image_t dst_img;
|
image_t dst_img;
|
||||||
dst_img.w = self->width;
|
dst_img.w = self->width;
|
||||||
dst_img.h = self->height;
|
dst_img.h = self->height;
|
||||||
@ -412,7 +518,50 @@ static void display_set_backlight(py_display_obj_t *self, uint32_t intensity) {
|
|||||||
}
|
}
|
||||||
#endif // OMV_DISPLAY_BL_PIN
|
#endif // OMV_DISPLAY_BL_PIN
|
||||||
|
|
||||||
|
#ifdef OMV_DSI_DISPLAY_CONTROLLER
|
||||||
|
int display_dsi_write(py_display_obj_t *self, uint8_t cmd, uint8_t *args, size_t n_args, bool dcs) {
|
||||||
|
HAL_StatusTypeDef status = HAL_ERROR;
|
||||||
|
if (n_args == 0) {
|
||||||
|
status = HAL_DSI_ShortWrite(&display.hdsi, self->vcid, (dcs == true) ?
|
||||||
|
DSI_DCS_SHORT_PKT_WRITE_P0 : DSI_GEN_SHORT_PKT_WRITE_P1, cmd, 0x00);
|
||||||
|
} else if (n_args == 1) {
|
||||||
|
status = HAL_DSI_ShortWrite(&display.hdsi, self->vcid, (dcs == true) ?
|
||||||
|
DSI_DCS_SHORT_PKT_WRITE_P1 : DSI_GEN_SHORT_PKT_WRITE_P2, cmd, args[0]);
|
||||||
|
} else {
|
||||||
|
status = HAL_DSI_LongWrite(&display.hdsi, self->vcid, (dcs == true) ?
|
||||||
|
DSI_DCS_LONG_PKT_WRITE : DSI_GEN_LONG_PKT_WRITE, n_args, cmd, args);
|
||||||
|
}
|
||||||
|
if (status != HAL_OK) {
|
||||||
|
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("DSI write command failed"));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int display_dsi_read(py_display_obj_t *self, uint8_t cmd, uint8_t *args,
|
||||||
|
size_t n_args, uint8_t *buf, size_t len, bool dcs) {
|
||||||
|
HAL_StatusTypeDef status = HAL_ERROR;
|
||||||
|
uint8_t params[] = { cmd, (args == NULL) ? 0 : args[0] };
|
||||||
|
if (n_args == 0) {
|
||||||
|
// For generic commands, the HAL expects cmd in ParametersTable[0U]
|
||||||
|
status = HAL_DSI_Read(&display.hdsi, self->vcid, buf, len, (dcs == true) ?
|
||||||
|
DSI_DCS_SHORT_PKT_READ : DSI_GEN_SHORT_PKT_READ_P1, cmd, params);
|
||||||
|
} else if (n_args == 1) {
|
||||||
|
status = HAL_DSI_Read(&display.hdsi, self->vcid,
|
||||||
|
buf, len, DSI_GEN_SHORT_PKT_READ_P2, 0, params);
|
||||||
|
}
|
||||||
|
if (status != HAL_OK) {
|
||||||
|
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("DSI read command failed"));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void display_deinit(py_display_obj_t *self) {
|
static void display_deinit(py_display_obj_t *self) {
|
||||||
|
#ifdef OMV_DSI_DISPLAY_CONTROLLER
|
||||||
|
HAL_DSI_DeInit(&display.hdsi);
|
||||||
|
HAL_NVIC_DisableIRQ(DSI_IRQn);
|
||||||
|
#endif
|
||||||
|
|
||||||
HAL_LTDC_DeInit(&display.hltdc);
|
HAL_LTDC_DeInit(&display.hltdc);
|
||||||
HAL_NVIC_DisableIRQ(LTDC_IRQn);
|
HAL_NVIC_DisableIRQ(LTDC_IRQn);
|
||||||
|
|
||||||
@ -435,13 +584,15 @@ static void display_deinit(py_display_obj_t *self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_t display_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
mp_obj_t display_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||||
enum { ARG_framesize, ARG_refresh, ARG_display_on, ARG_triple_buffer, ARG_portrait };
|
enum { ARG_framesize, ARG_refresh, ARG_display_on, ARG_triple_buffer, ARG_portrait, ARG_channel, ARG_controller };
|
||||||
static const mp_arg_t allowed_args[] = {
|
static const mp_arg_t allowed_args[] = {
|
||||||
{ MP_QSTR_framesize, MP_ARG_INT, {.u_int = DISPLAY_RESOLUTION_FWVGA } },
|
{ MP_QSTR_framesize, MP_ARG_INT, {.u_int = DISPLAY_RESOLUTION_FWVGA } },
|
||||||
{ MP_QSTR_refresh, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 60 } },
|
{ MP_QSTR_refresh, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 60 } },
|
||||||
{ MP_QSTR_display_on, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} },
|
{ MP_QSTR_display_on, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} },
|
||||||
{ MP_QSTR_triple_buffer, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} },
|
{ MP_QSTR_triple_buffer, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} },
|
||||||
{ MP_QSTR_portrait, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
|
{ MP_QSTR_portrait, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
|
||||||
|
{ MP_QSTR_channel, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0 } },
|
||||||
|
{ MP_QSTR_controller, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = MP_ROM_NONE} },
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parse args.
|
// Parse args.
|
||||||
@ -456,7 +607,12 @@ mp_obj_t display_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
|
|||||||
}
|
}
|
||||||
|
|
||||||
py_display_obj_t *self = (py_display_obj_t *) m_new_obj_with_finaliser(py_display_obj_t);
|
py_display_obj_t *self = (py_display_obj_t *) m_new_obj_with_finaliser(py_display_obj_t);
|
||||||
|
#ifdef OMV_DSI_DISPLAY_CONTROLLER
|
||||||
|
self->base.type = &py_dsi_display_type;
|
||||||
|
#else
|
||||||
self->base.type = &py_rgb_display_type;
|
self->base.type = &py_rgb_display_type;
|
||||||
|
#endif
|
||||||
|
self->vcid = args[ARG_channel].u_int;
|
||||||
self->refresh = args[ARG_refresh].u_int;
|
self->refresh = args[ARG_refresh].u_int;
|
||||||
self->display_on = args[ARG_display_on].u_bool;
|
self->display_on = args[ARG_display_on].u_bool;
|
||||||
self->bgr = false;
|
self->bgr = false;
|
||||||
@ -471,6 +627,7 @@ mp_obj_t display_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
|
|||||||
self->width = display_modes[self->framesize].hactive;
|
self->width = display_modes[self->framesize].hactive;
|
||||||
self->height = display_modes[self->framesize].vactive;
|
self->height = display_modes[self->framesize].vactive;
|
||||||
}
|
}
|
||||||
|
self->controller = args[ARG_controller].u_obj;
|
||||||
|
|
||||||
// Store state to access it from IRQ handlers or callbacks
|
// Store state to access it from IRQ handlers or callbacks
|
||||||
display.self = self;
|
display.self = self;
|
||||||
@ -481,6 +638,21 @@ mp_obj_t display_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
|
|||||||
// Init LTDC controller
|
// Init LTDC controller
|
||||||
ltdc_init(self);
|
ltdc_init(self);
|
||||||
|
|
||||||
|
#ifdef OMV_DSI_DISPLAY_CONTROLLER
|
||||||
|
// Init DSI controller
|
||||||
|
dsi_init(self);
|
||||||
|
|
||||||
|
// Init the display controller.
|
||||||
|
if (self->controller != mp_const_none) {
|
||||||
|
mp_obj_t dest[3];
|
||||||
|
mp_load_method_maybe(self->controller, MP_QSTR_init, dest);
|
||||||
|
if (dest[0] != MP_OBJ_NULL) {
|
||||||
|
dest[2] = MP_OBJ_FROM_PTR(self);
|
||||||
|
mp_call_method_n_kw(1, 0, dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef OMV_DISPLAY_BL_PIN
|
#ifdef OMV_DISPLAY_BL_PIN
|
||||||
if (self->display_on) {
|
if (self->display_on) {
|
||||||
display_set_backlight(self, 255); // to on state
|
display_set_backlight(self, 255); // to on state
|
||||||
@ -497,8 +669,13 @@ STATIC const py_display_p_t py_display_p = {
|
|||||||
#ifdef OMV_DISPLAY_BL_PIN
|
#ifdef OMV_DISPLAY_BL_PIN
|
||||||
.set_backlight = display_set_backlight,
|
.set_backlight = display_set_backlight,
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef OMV_DSI_DISPLAY_CONTROLLER
|
||||||
|
.dsi_write = display_dsi_write,
|
||||||
|
.dsi_read = display_dsi_read,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef OMV_RGB_DISPLAY_CONTROLLER
|
||||||
MP_DEFINE_CONST_OBJ_TYPE(
|
MP_DEFINE_CONST_OBJ_TYPE(
|
||||||
py_rgb_display_type,
|
py_rgb_display_type,
|
||||||
MP_QSTR_RGBDisplay,
|
MP_QSTR_RGBDisplay,
|
||||||
@ -507,4 +684,17 @@ MP_DEFINE_CONST_OBJ_TYPE(
|
|||||||
protocol, &py_display_p,
|
protocol, &py_display_p,
|
||||||
locals_dict, &py_display_locals_dict
|
locals_dict, &py_display_locals_dict
|
||||||
);
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OMV_DSI_DISPLAY_CONTROLLER
|
||||||
|
MP_DEFINE_CONST_OBJ_TYPE(
|
||||||
|
py_dsi_display_type,
|
||||||
|
MP_QSTR_DSIDisplay,
|
||||||
|
MP_TYPE_FLAG_NONE,
|
||||||
|
make_new, display_make_new,
|
||||||
|
protocol, &py_display_p,
|
||||||
|
locals_dict, &py_display_locals_dict
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // MICROPY_PY_DISPLAY
|
#endif // MICROPY_PY_DISPLAY
|
||||||
|
|||||||
@ -601,7 +601,19 @@ void HAL_JPEG_MspDeInit(JPEG_HandleTypeDef *hjpeg) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(OMV_RGB_DISPLAY_CONTROLLER)
|
#if defined(OMV_DSI_DISPLAY_CONTROLLER)
|
||||||
|
void HAL_DSI_MspInit(DSI_HandleTypeDef *hdsi) {
|
||||||
|
__HAL_RCC_DSI_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HAL_DSI_MspDeInit(DSI_HandleTypeDef *hdsi) {
|
||||||
|
__HAL_RCC_DSI_FORCE_RESET();
|
||||||
|
__HAL_RCC_DSI_RELEASE_RESET();
|
||||||
|
__HAL_RCC_DSI_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(OMV_RGB_DISPLAY_CONTROLLER) || defined(OMV_DSI_DISPLAY_CONTROLLER)
|
||||||
void HAL_LTDC_MspInit(LTDC_HandleTypeDef *hltdc) {
|
void HAL_LTDC_MspInit(LTDC_HandleTypeDef *hltdc) {
|
||||||
#if defined(OMV_RGB_DISPLAY_R0_PIN)
|
#if defined(OMV_RGB_DISPLAY_R0_PIN)
|
||||||
const omv_gpio_t ltdc_pins[] = {
|
const omv_gpio_t ltdc_pins[] = {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user