Add ft5x06 touch screen lcd support

This commit is contained in:
Kwabena W. Agyeman 2020-11-22 11:02:19 -08:00
parent d24649bdb4
commit 293f569597
6 changed files with 346 additions and 0 deletions

View File

@ -310,6 +310,7 @@ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/py/, \
py_image.o \
py_time.o \
py_lcd.o \
py_lcd_touch.o \
py_tv.o \
py_fir.o \
py_gif.o \

View File

@ -97,6 +97,7 @@ SRCS += $(addprefix py/, \
py_image.c \
py_time.c \
py_lcd.c \
py_lcd_touch.c \
py_tv.c \
py_fir.c \
py_gif.c \

View File

@ -11,6 +11,7 @@
#include STM32_HAL_H
#include "extint.h"
#include "spi.h"
#include "py_lcd_touch.h"
#include "py_helper.h"
#include "extmod/machine_i2c.h"
#include "omv_boardconfig.h"
@ -1209,6 +1210,9 @@ STATIC mp_obj_t py_lcd_deinit()
#ifdef OMV_DVI_PRESENT
if ((lcd_type == LCD_DISPLAY_WITH_HDMI) || (lcd_type == LCD_DISPLAY_ONLY_HDMI)) ltdc_dvi_deinit();
#endif // OMV_DVI_PRESENT
#ifdef OMV_TOUCH_PRESENT
if ((lcd_type == LCD_DISPLAY) || (lcd_type == LCD_DISPLAY_WITH_HDMI)) lcd_touch_deinit();
#endif // OMV_TOUCH_PRESENT
break;
}
#endif
@ -1273,6 +1277,9 @@ STATIC mp_obj_t py_lcd_init(uint n_args, const mp_obj_t *args, mp_map_t *kw_args
#ifdef OMV_DVI_PRESENT
if ((type == LCD_DISPLAY_WITH_HDMI) || (type == LCD_DISPLAY_ONLY_HDMI)) ltdc_dvi_init();
#endif // OMV_DVI_PRESENT
#ifdef OMV_TOUCH_PRESENT
if ((type == LCD_DISPLAY) || (type == LCD_DISPLAY_WITH_HDMI)) lcd_touch_init();
#endif // OMV_TOUCH_PRESENT
lcd_width = resolution_w_h[frame_size][0];
lcd_height = resolution_w_h[frame_size][1];
lcd_type = LCD_DISPLAY;
@ -1404,6 +1411,85 @@ STATIC mp_obj_t py_lcd_register_hotplug_cb(mp_obj_t cb)
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_lcd_register_hotplug_cb_obj, py_lcd_register_hotplug_cb);
STATIC mp_obj_t py_lcd_update_touch_points()
{
#ifdef OMV_TOUCH_PRESENT
return lcd_touch_update_touch_points();
#else
return mp_const_none;
#endif
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_lcd_update_touch_points_obj, py_lcd_update_touch_points);
STATIC mp_obj_t py_lcd_register_touch_cb(mp_obj_t cb)
{
#ifdef OMV_TOUCH_PRESENT
lcd_touch_register_touch_cb(cb);
#endif
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_lcd_register_touch_cb_obj, py_lcd_register_touch_cb);
STATIC mp_obj_t py_lcd_get_gesture()
{
#ifdef OMV_TOUCH_PRESENT
return lcd_touch_get_gesture();
#else
return mp_const_none;
#endif
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_lcd_get_gesture_obj, py_lcd_get_gesture);
STATIC mp_obj_t py_lcd_get_points()
{
#ifdef OMV_TOUCH_PRESENT
return lcd_touch_get_points();
#else
return mp_const_none;
#endif
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_lcd_get_points_obj, py_lcd_get_points);
STATIC mp_obj_t py_lcd_get_point_flag(mp_obj_t index)
{
#ifdef OMV_TOUCH_PRESENT
return lcd_touch_get_point_flag(index);
#else
return mp_const_none;
#endif
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_lcd_get_point_flag_obj, py_lcd_get_point_flag);
STATIC mp_obj_t py_lcd_get_point_id(mp_obj_t index)
{
#ifdef OMV_TOUCH_PRESENT
return lcd_touch_get_point_id(index);
#else
return mp_const_none;
#endif
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_lcd_get_point_id_obj, py_lcd_get_point_id);
STATIC mp_obj_t py_lcd_get_point_x_position(mp_obj_t index)
{
#ifdef OMV_TOUCH_PRESENT
return lcd_touch_get_point_x_position(index);
#else
return mp_const_none;
#endif
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_lcd_get_point_x_position_obj, py_lcd_get_point_x_position);
STATIC mp_obj_t py_lcd_get_point_y_position(mp_obj_t index)
{
#ifdef OMV_TOUCH_PRESENT
return lcd_touch_get_point_y_position(index);
#else
return mp_const_none;
#endif
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_lcd_get_point_y_position_obj, py_lcd_get_point_y_position);
STATIC mp_obj_t py_lcd_display(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
image_t *arg_img = py_helper_arg_to_image_mutable(args[0]);
@ -1581,6 +1667,16 @@ STATIC const mp_rom_map_elem_t globals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_UXGA), MP_ROM_INT(LCD_DISPLAY_UXGA) },
{ MP_ROM_QSTR(MP_QSTR_HD), MP_ROM_INT(LCD_DISPLAY_HD) },
{ MP_ROM_QSTR(MP_QSTR_FHD), MP_ROM_INT(LCD_DISPLAY_FHD) },
{ MP_ROM_QSTR(MP_QSTR_LCD_GESTURE_MOVE_UP), MP_ROM_INT(PY_LCD_TOUCH_GESTURE_MOVE_UP) },
{ MP_ROM_QSTR(MP_QSTR_LCD_GESTURE_MOVE_LEFT), MP_ROM_INT(PY_LCD_TOUCH_GESTURE_MOVE_LEFT) },
{ MP_ROM_QSTR(MP_QSTR_LCD_GESTURE_MOVE_DOWN), MP_ROM_INT(PY_LCD_TOUCH_GESTURE_MOVE_DOWN) },
{ MP_ROM_QSTR(MP_QSTR_LCD_GESTURE_MOVE_RIGHT), MP_ROM_INT(PY_LCD_TOUCH_GESTURE_MOVE_RIGHT) },
{ MP_ROM_QSTR(MP_QSTR_LCD_GESTURE_ZOOM_IN), MP_ROM_INT(PY_LCD_TOUCH_GESTURE_ZOOM_IN) },
{ MP_ROM_QSTR(MP_QSTR_LCD_GESTURE_ZOOM_OUT), MP_ROM_INT(PY_LCD_TOUCH_GESTURE_ZOOM_OUT) },
{ MP_ROM_QSTR(MP_QSTR_LCD_GESTURE_NONE), MP_ROM_INT(PY_LCD_TOUCH_GESTURE_NONE) },
{ MP_ROM_QSTR(MP_QSTR_LCD_FLAG_PRESSED), MP_ROM_INT(PY_LCD_TOUCH_EVENT_PUT_DOWN) },
{ MP_ROM_QSTR(MP_QSTR_LCD_FLAG_RELEASED), MP_ROM_INT(PY_LCD_TOUCH_EVENT_PUT_UP) },
{ MP_ROM_QSTR(MP_QSTR_LCD_FLAG_MOVED), MP_ROM_INT(PY_LCD_TOUCH_EVENT_CONTACT) },
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&py_lcd_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&py_lcd_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&py_lcd_width_obj) },
@ -1595,6 +1691,14 @@ STATIC const mp_rom_map_elem_t globals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_get_display_connected), MP_ROM_PTR(&py_lcd_get_display_connected_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_display_id_data), MP_ROM_PTR(&py_lcd_get_display_id_data_obj) },
{ MP_ROM_QSTR(MP_QSTR_register_hotplug_cb), MP_ROM_PTR(&py_lcd_register_hotplug_cb_obj) },
{ MP_ROM_QSTR(MP_QSTR_update_touch_points), MP_ROM_PTR(&py_lcd_update_touch_points_obj) },
{ MP_ROM_QSTR(MP_QSTR_register_touch_cb), MP_ROM_PTR(&py_lcd_register_touch_cb_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_gesture), MP_ROM_PTR(&py_lcd_get_gesture_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_points), MP_ROM_PTR(&py_lcd_get_points_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_point_flag), MP_ROM_PTR(&py_lcd_get_point_flag_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_point_id), MP_ROM_PTR(&py_lcd_get_point_id_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_point_x_position), MP_ROM_PTR(&py_lcd_get_point_x_position_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_point_y_position), MP_ROM_PTR(&py_lcd_get_point_y_position_obj) },
{ MP_ROM_QSTR(MP_QSTR_display), MP_ROM_PTR(&py_lcd_display_obj) },
{ MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&py_lcd_clear_obj) },
};

185
src/omv/py/py_lcd_touch.c Normal file
View File

@ -0,0 +1,185 @@
/*
* This file is part of the OpenMV project.
*
* Copyright (c) 2013-2019 Ibrahim Abdelkader <iabdalkader@openmv.io>
* Copyright (c) 2013-2019 Kwabena W. Agyeman <kwagyeman@openmv.io>
*
* This work is licensed under the MIT license, see the file LICENSE for details.
*
* LCD Python module.
*/
#include STM32_HAL_H
#include "extint.h"
#include "extmod/machine_i2c.h"
#include "py_helper.h"
#include "py_lcd_touch.h"
#include "omv_boardconfig.h"
#ifdef OMV_TOUCH_PRESENT
#define FT5X06_I2C_ADDR 0x38
mp_obj_base_t *lcd_touch_bus = NULL;
mp_obj_t lcd_touch_user_cb = NULL;
#define NUM_TOUCH_POINTS 5
volatile uint8_t lcd_touch_gesture = 0;
volatile uint8_t lcd_touch_points = 0, lcd_touch_points_old = 0;
volatile uint8_t lcd_touch_flag[NUM_TOUCH_POINTS] = {};
volatile uint8_t lcd_touch_id[NUM_TOUCH_POINTS] = {};
volatile uint16_t lcd_touch_x_position[NUM_TOUCH_POINTS] = {};
volatile uint16_t lcd_touch_y_position[NUM_TOUCH_POINTS] = {};
mp_obj_t lcd_touch_get_gesture()
{
return mp_obj_new_int(lcd_touch_gesture);
}
mp_obj_t lcd_touch_get_points()
{
return mp_obj_new_int(lcd_touch_points);
}
mp_obj_t lcd_touch_get_point_flag(mp_obj_t index)
{
int i = mp_obj_get_int(index);
if ((i < 0) || (NUM_TOUCH_POINTS <= i)) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Index out of bounds!"));
return mp_obj_new_int(lcd_touch_flag[i]);
}
mp_obj_t lcd_touch_get_point_id(mp_obj_t index)
{
int i = mp_obj_get_int(index);
if ((i < 0) || (NUM_TOUCH_POINTS <= i)) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Index out of bounds!"));
return mp_obj_new_int(lcd_touch_id[i]);
}
mp_obj_t lcd_touch_get_point_x_position(mp_obj_t index)
{
int i = mp_obj_get_int(index);
if ((i < 0) || (NUM_TOUCH_POINTS <= i)) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Index out of bounds!"));
return mp_obj_new_int(lcd_touch_x_position[i]);
}
mp_obj_t lcd_touch_get_point_y_position(mp_obj_t index)
{
int i = mp_obj_get_int(index);
if ((i < 0) || (NUM_TOUCH_POINTS <= i)) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Index out of bounds!"));
return mp_obj_new_int(lcd_touch_y_position[i]);
}
mp_obj_t lcd_touch_update_touch_points()
{
mp_obj_base_t *bus = lcd_touch_bus ? lcd_touch_bus : ((mp_obj_base_t *) machine_i2c_type.make_new(&machine_i2c_type, 3, 0, (const mp_obj_t []) {
MP_OBJ_NEW_SMALL_INT(-1), (mp_obj_t) OMV_TOUCH_SCL_PIN, (mp_obj_t) OMV_TOUCH_SDA_PIN
}));
if (mp_machine_soft_i2c_transfer(bus, FT5X06_I2C_ADDR, 1, &((mp_machine_i2c_buf_t) {
.len = 1, .buf = (uint8_t []) {0x01} // addr
}), MP_MACHINE_I2C_FLAG_STOP) == 1) {
uint8_t regs[30];
if (mp_machine_soft_i2c_transfer(bus, FT5X06_I2C_ADDR, 1, &((mp_machine_i2c_buf_t) {
.len = 30, .buf = regs
}), MP_MACHINE_I2C_FLAG_READ | MP_MACHINE_I2C_FLAG_STOP) == 0) {
int points = regs[1] & 0xF;
if (points > NUM_TOUCH_POINTS) points = NUM_TOUCH_POINTS;
// Update valid touch points...
for (int i = 0; i < points; i++) {
lcd_touch_flag[i] = regs[2 + (i * 6)] >> 6;
lcd_touch_id[i] = regs[4 + (i * 6)] >> 4;
lcd_touch_x_position[i] = ((regs[2 + (i * 6)] & 0xF) << 8) | regs[3 + (i * 6)];
lcd_touch_y_position[i] = ((regs[4 + (i * 6)] & 0xF) << 8) | regs[5 + (i * 6)];
}
// Reset invalid touch points...
for (int i = points; i < NUM_TOUCH_POINTS; i++) {
lcd_touch_flag[i] = PY_LCD_TOUCH_EVENT_PUT_UP;
}
// Latch gesture as long as touch is valid.
if (points && regs[0]) lcd_touch_gesture = regs[0];
else if (!points) lcd_touch_gesture = PY_LCD_TOUCH_GESTURE_NONE;
// When the number of points increase the result is immediately valid.
if (points >= lcd_touch_points) {
lcd_touch_points = points;
// When the number of points decrease track the last valid number of events.
} else if (points <= lcd_touch_points_old) {
lcd_touch_points = lcd_touch_points_old;
}
lcd_touch_points_old = points;
return mp_obj_new_int(lcd_touch_points);
}
}
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Failed to update the number of touch points!"));
}
STATIC mp_obj_t lcd_touch_extint_callback(mp_obj_t line)
{
if (lcd_touch_user_cb) mp_call_function_1(lcd_touch_user_cb, lcd_touch_update_touch_points());
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(lcd_touch_extint_callback_obj, lcd_touch_extint_callback);
void lcd_touch_deinit()
{
extint_disable(OMV_TOUCH_INT_PIN->pin);
lcd_touch_user_cb = NULL;
lcd_touch_bus = NULL;
lcd_touch_gesture = 0;
lcd_touch_points = lcd_touch_points_old = 0;
memset((void *) lcd_touch_flag, 0, sizeof(lcd_touch_flag));
memset((void *) lcd_touch_id, 0, sizeof(lcd_touch_id));
memset((void *) lcd_touch_x_position, 0, sizeof(lcd_touch_x_position));
memset((void *) lcd_touch_y_position, 0, sizeof(lcd_touch_y_position));
HAL_GPIO_WritePin(OMV_TOUCH_RESET_PIN->gpio, OMV_TOUCH_RESET_PIN->pin_mask, GPIO_PIN_RESET);
HAL_Delay(1);
HAL_GPIO_WritePin(OMV_TOUCH_RESET_PIN->gpio, OMV_TOUCH_RESET_PIN->pin_mask, GPIO_PIN_SET);
HAL_Delay(39);
HAL_GPIO_DeInit(OMV_TOUCH_INT_PIN->gpio, OMV_TOUCH_INT_PIN->pin_mask);
HAL_GPIO_DeInit(OMV_TOUCH_SDA_PIN->gpio, OMV_TOUCH_SDA_PIN->pin_mask);
HAL_GPIO_DeInit(OMV_TOUCH_SCL_PIN->gpio, OMV_TOUCH_SCL_PIN->pin_mask);
HAL_GPIO_DeInit(OMV_TOUCH_RESET_PIN->gpio, OMV_TOUCH_RESET_PIN->pin_mask);
}
void lcd_touch_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStructure.Pin = OMV_TOUCH_RESET_PIN->pin_mask;
HAL_GPIO_Init(OMV_TOUCH_RESET_PIN->gpio, &GPIO_InitStructure);
HAL_GPIO_WritePin(OMV_TOUCH_RESET_PIN->gpio, OMV_TOUCH_RESET_PIN->pin_mask, GPIO_PIN_RESET);
HAL_Delay(1);
HAL_GPIO_WritePin(OMV_TOUCH_RESET_PIN->gpio, OMV_TOUCH_RESET_PIN->pin_mask, GPIO_PIN_SET);
HAL_Delay(39);
lcd_touch_bus = (mp_obj_base_t *) machine_i2c_type.make_new(&machine_i2c_type, 3, 0, (const mp_obj_t []) {
MP_OBJ_NEW_SMALL_INT(-1), (mp_obj_t) OMV_TOUCH_SCL_PIN, (mp_obj_t) OMV_TOUCH_SDA_PIN
});
if (mp_machine_soft_i2c_transfer(lcd_touch_bus, FT5X06_I2C_ADDR, 1, &((mp_machine_i2c_buf_t) {
.len = 2, .buf = (uint8_t []) {0x00, 0x00} // addr, DEVICE_MODE
}), MP_MACHINE_I2C_FLAG_STOP) == 2) {
extint_register((mp_obj_t) OMV_TOUCH_INT_PIN, GPIO_MODE_IT_FALLING, GPIO_PULLUP, (mp_obj_t) &lcd_touch_extint_callback_obj, true);
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Touch init failed!"));
}
}
void lcd_touch_register_touch_cb(mp_obj_t cb)
{
extint_disable(OMV_TOUCH_INT_PIN->pin);
lcd_touch_user_cb = cb;
if (cb != mp_const_none) extint_enable(OMV_TOUCH_INT_PIN->pin);
}
#endif // OMV_TOUCH_PRESENT

37
src/omv/py/py_lcd_touch.h Normal file
View File

@ -0,0 +1,37 @@
/*
* This file is part of the OpenMV project.
*
* Copyright (c) 2013-2019 Ibrahim Abdelkader <iabdalkader@openmv.io>
* Copyright (c) 2013-2019 Kwabena W. Agyeman <kwagyeman@openmv.io>
*
* This work is licensed under the MIT license, see the file LICENSE for details.
*
* LCD Python module.
*/
#ifndef __PY_LCD_TOUCH_H__
#define __PY_LCD_TOUCH_H__
typedef enum py_lcd_touch_gesture {
PY_LCD_TOUCH_GESTURE_MOVE_UP = 0x1C, // Rotated by 90 degrees - 0x10,
PY_LCD_TOUCH_GESTURE_MOVE_LEFT = 0x10, // Rotated by 90 degrees - 0x14,
PY_LCD_TOUCH_GESTURE_MOVE_DOWN = 0x14, // Rotated by 90 degrees - 0x18,
PY_LCD_TOUCH_GESTURE_MOVE_RIGHT = 0x18, // Rotated by 90 degrees - 0x1C,
PY_LCD_TOUCH_GESTURE_ZOOM_IN = 0x48,
PY_LCD_TOUCH_GESTURE_ZOOM_OUT = 0x49,
PY_LCD_TOUCH_GESTURE_NONE = 0x00
} py_lcd_touch_gesture_t;
typedef enum py_lcd_touch_event {
PY_LCD_TOUCH_EVENT_PUT_DOWN = 0x0,
PY_LCD_TOUCH_EVENT_PUT_UP = 0x1,
PY_LCD_TOUCH_EVENT_CONTACT = 0x2
} py_lcd_touch_event_t;
void lcd_touch_init();
void lcd_touch_deinit();
mp_obj_t lcd_touch_update_touch_points();
void lcd_touch_register_touch_cb(mp_obj_t cb);
mp_obj_t lcd_touch_get_gesture();
mp_obj_t lcd_touch_get_points();
mp_obj_t lcd_touch_get_point_flag(mp_obj_t index);
mp_obj_t lcd_touch_get_point_id(mp_obj_t index);
mp_obj_t lcd_touch_get_point_x_position(mp_obj_t index);
mp_obj_t lcd_touch_get_point_y_position(mp_obj_t index);
#endif // __PY_LCD_TOUCH_H__

View File

@ -1199,6 +1199,24 @@ Q(get_backlight)
Q(get_display_connected)
Q(get_display_id_data)
Q(register_hotplug_cb)
Q(update_touch_points)
Q(register_touch_cb)
Q(get_gesture)
Q(LCD_GESTURE_MOVE_UP)
Q(LCD_GESTURE_MOVE_LEFT)
Q(LCD_GESTURE_MOVE_DOWN)
Q(LCD_GESTURE_MOVE_RIGHT)
Q(LCD_GESTURE_ZOOM_IN)
Q(LCD_GESTURE_ZOOM_OUT)
Q(LCD_GESTURE_NONE)
Q(get_points)
Q(get_point_flag)
Q(LCD_FLAG_PRESSED)
Q(LCD_FLAG_RELEASED)
Q(LCD_FLAG_MOVED)
Q(get_point_id)
Q(get_point_x_position)
Q(get_point_y_position)
Q(display)
Q(clear)