[imxrt 1060] support touchpad

Signed-off-by: Ting Liu <ting.liu@nxp.com>
This commit is contained in:
Ting Liu 2022-05-16 22:27:06 +08:00 committed by guo
parent f92c26a60b
commit 880fc2f59a
12 changed files with 1792 additions and 0 deletions

View File

@ -1,13 +1,246 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
* Copyright 2022 NXP
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-10-18 Meco Man The first version
* 2022-05-17 Ting Liu Support touchpad
*/
#define LOG_TAG "LVGL.port.indev"
#include <drv_log.h>
#include "lvgl.h"
#include "board.h"
#include "fsl_video_common.h"
#include "fsl_lpi2c.h"
#include "fsl_gpio.h"
#ifdef DEMO_PANEL_RK043FN66HS
#include "fsl_gt911.h"
#else
#include "fsl_ft5406_rt.h"
#endif
#if LV_USE_GPU_NXP_PXP
#include "src/gpu/lv_gpu_nxp_pxp.h"
#include "src/gpu/lv_gpu_nxp_pxp_osa.h"
#endif
/*******************************************************************************
* Definitions
******************************************************************************/
/* @Brief Board touch panel configuration */
#define BOARD_TOUCH_I2C_BASEADDR LPI2C1
#define BOARD_TOUCH_RST_GPIO GPIO1
#define BOARD_TOUCH_RST_PIN 2
#define BOARD_TOUCH_INT_GPIO GPIO1
#define BOARD_TOUCH_INT_PIN 11
/* Macros for the touch touch controller. */
#define TOUCH_I2C LPI2C1
/* Select USB1 PLL (480 MHz) as master lpi2c clock source */
#define TOUCH_LPI2C_CLOCK_SOURCE_SELECT (0U)
/* Clock divider for master lpi2c clock source */
#define TOUCH_LPI2C_CLOCK_SOURCE_DIVIDER (5U)
#define TOUCH_I2C_CLOCK_FREQ ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / 8) / (TOUCH_LPI2C_CLOCK_SOURCE_DIVIDER + 1U))
#define TOUCH_I2C_BAUDRATE 100000U
/*******************************************************************************
* Prototypes
******************************************************************************/
static void DEMO_InitTouch(void);
static void DEMO_ReadTouch(lv_indev_drv_t *drv, lv_indev_data_t *data);
#ifdef DEMO_PANEL_RK043FN66HS
static void BOARD_PullTouchResetPin(bool pullUp);
static void BOARD_ConfigTouchIntPin(gt911_int_pin_mode_t mode);
#endif
/*******************************************************************************
* Variables
******************************************************************************/
#ifdef DEMO_PANEL_RK043FN66HS
static gt911_handle_t s_touchHandle;
static const gt911_config_t s_touchConfig = {
.I2C_SendFunc = BOARD_Touch_I2C_Send,
.I2C_ReceiveFunc = BOARD_Touch_I2C_Receive,
.pullResetPinFunc = BOARD_PullTouchResetPin,
.intPinFunc = BOARD_ConfigTouchIntPin,
.timeDelayMsFunc = VIDEO_DelayMs,
.touchPointNum = 1,
.i2cAddrMode = kGT911_I2cAddrMode0,
.intTrigMode = kGT911_IntRisingEdge,
};
static int s_touchResolutionX;
static int s_touchResolutionY;
#else
static ft5406_rt_handle_t touchHandle;
#endif
void lv_port_indev_init(void)
{
static lv_indev_drv_t indev_drv;
/*------------------
* Touchpad
* -----------------*/
/*Initialize your touchpad */
DEMO_InitTouch();
/*Register a touchpad input device*/
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = DEMO_ReadTouch;
lv_indev_drv_register(&indev_drv);
}
#ifdef DEMO_PANEL_RK043FN66HS
static void BOARD_PullTouchResetPin(bool pullUp)
{
if (pullUp)
{
GPIO_PinWrite(BOARD_TOUCH_RST_GPIO, BOARD_TOUCH_RST_PIN, 1);
}
else
{
GPIO_PinWrite(BOARD_TOUCH_RST_GPIO, BOARD_TOUCH_RST_PIN, 0);
}
}
static void BOARD_ConfigTouchIntPin(gt911_int_pin_mode_t mode)
{
if (mode == kGT911_IntPinInput)
{
BOARD_TOUCH_INT_GPIO->GDIR &= ~(1UL << BOARD_TOUCH_INT_PIN);
}
else
{
if (mode == kGT911_IntPinPullDown)
{
GPIO_PinWrite(BOARD_TOUCH_INT_GPIO, BOARD_TOUCH_INT_PIN, 0);
}
else
{
GPIO_PinWrite(BOARD_TOUCH_INT_GPIO, BOARD_TOUCH_INT_PIN, 1);
}
BOARD_TOUCH_INT_GPIO->GDIR |= (1UL << BOARD_TOUCH_INT_PIN);
}
}
/*Initialize your touchpad*/
static void DEMO_InitTouch(void)
{
status_t status;
const gpio_pin_config_t resetPinConfig = {
.direction = kGPIO_DigitalOutput, .outputLogic = 0, .interruptMode = kGPIO_NoIntmode};
GPIO_PinInit(BOARD_TOUCH_INT_GPIO, BOARD_TOUCH_INT_PIN, &resetPinConfig);
GPIO_PinInit(BOARD_TOUCH_RST_GPIO, BOARD_TOUCH_RST_PIN, &resetPinConfig);
/*Clock setting for LPI2C*/
CLOCK_SetMux(kCLOCK_Lpi2cMux, TOUCH_LPI2C_CLOCK_SOURCE_SELECT);
CLOCK_SetDiv(kCLOCK_Lpi2cDiv, TOUCH_LPI2C_CLOCK_SOURCE_DIVIDER);
BOARD_LPI2C_Init(TOUCH_I2C, TOUCH_I2C_CLOCK_FREQ);
status = GT911_Init(&s_touchHandle, &s_touchConfig);
if (kStatus_Success != status)
{
//PRINTF("Touch IC initialization failed\r\n");
assert(false);
}
GT911_GetResolution(&s_touchHandle, &s_touchResolutionX, &s_touchResolutionY);
}
/* Will be called by the library to read the touchpad */
static void DEMO_ReadTouch(lv_indev_drv_t *drv, lv_indev_data_t *data)
{
static int touch_x = 0;
static int touch_y = 0;
if (kStatus_Success == GT911_GetSingleTouch(&s_touchHandle, &touch_x, &touch_y))
{
data->state = LV_INDEV_STATE_PR;
}
else
{
data->state = LV_INDEV_STATE_REL;
}
/*Set the last pressed coordinates*/
data->point.x = touch_x * LCD_WIDTH / s_touchResolutionX;
data->point.y = touch_y * LCD_HEIGHT / s_touchResolutionY;
}
#else
/*Initialize your touchpad*/
static void DEMO_InitTouch(void)
{
status_t status;
lpi2c_master_config_t masterConfig = {0};
/*Clock setting for LPI2C*/
CLOCK_SetMux(kCLOCK_Lpi2cMux, TOUCH_LPI2C_CLOCK_SOURCE_SELECT);
CLOCK_SetDiv(kCLOCK_Lpi2cDiv, TOUCH_LPI2C_CLOCK_SOURCE_DIVIDER);
/*
* masterConfig.debugEnable = false;
* masterConfig.ignoreAck = false;
* masterConfig.pinConfig = kLPI2C_2PinOpenDrain;
* masterConfig.baudRate_Hz = 100000U;
* masterConfig.busIdleTimeout_ns = 0;
* masterConfig.pinLowTimeout_ns = 0;
* masterConfig.sdaGlitchFilterWidth_ns = 0;
* masterConfig.sclGlitchFilterWidth_ns = 0;
*/
LPI2C_MasterGetDefaultConfig(&masterConfig);
/* Change the default baudrate configuration */
masterConfig.baudRate_Hz = TOUCH_I2C_BAUDRATE;
/* Initialize the LPI2C master peripheral */
LPI2C_MasterInit(TOUCH_I2C, &masterConfig, TOUCH_I2C_CLOCK_FREQ);
/* Initialize touch panel controller */
status = FT5406_RT_Init(&touchHandle, TOUCH_I2C);
if (status != kStatus_Success)
{
//PRINTF("Touch panel init failed\n");
assert(0);
}
}
/* Will be called by the library to read the touchpad */
static void DEMO_ReadTouch(lv_indev_drv_t *drv, lv_indev_data_t *data)
{
touch_event_t touch_event;
static int touch_x = 0;
static int touch_y = 0;
data->state = LV_INDEV_STATE_REL;
if (kStatus_Success == FT5406_RT_GetSingleTouch(&touchHandle, &touch_event, &touch_x, &touch_y))
{
if ((touch_event == kTouch_Down) || (touch_event == kTouch_Contact))
{
data->state = LV_INDEV_STATE_PR;
}
}
/*Set the last pressed coordinates*/
data->point.x = touch_y;
data->point.y = touch_x;
}
#endif

View File

@ -68,11 +68,32 @@ menu "Onboard Peripheral Drivers"
default 2
endif
menuconfig BSP_USING_TOUCHPAD
bool "Enable TOUCHPAD"
select BSP_USING_PXP
select BSP_USING_CACHE
select BSP_USING_I2C
select BSP_USING_LCD
default n
if BSP_USING_TOUCHPAD
choice
prompt "Select panel"
default DEMO_PANEL_RK043FN02H
config DEMO_PANEL_RK043FN02H
bool "RK043FN02H-CT"
config DEMO_PANEL_RK043FN66HS
bool "RK043FN66HS-CTG"
endchoice
endif
config BSP_USING_LVGL
bool "Enable LVGL for LCD"
select BSP_USING_PXP
select BSP_USING_CACHE
select BSP_USING_LCD
select BSP_USING_TOUCHPAD
select PKG_USING_LVGL
default n
@ -100,6 +121,26 @@ menu "On-chip Peripheral Drivers"
select RT_USING_PIN
default y
menuconfig BSP_USING_I2C
bool "Enable I2C"
select RT_USING_I2C
default y
if BSP_USING_I2C
config BSP_USING_I2C1
bool
default y
choice
prompt "Select I2C1 badurate"
default HW_I2C1_BADURATE_100kHZ
config HW_I2C1_BADURATE_100kHZ
bool "Badurate 100kHZ"
config HW_I2C1_BADURATE_400kHZ
bool "Badurate 400kHZ"
endchoice
endif
menuconfig BSP_USING_LPUART
bool "Enable UART"
select RT_USING_SERIAL

View File

@ -12,6 +12,9 @@ MCUX_Config/pin_mux.c
MCUX_Config/dcd.c
""")
if GetDepend(['BSP_USING_TOUCHPAD']):
src += ['ports/touchpad.c']
CPPPATH = [cwd,cwd + '/MCUX_Config',cwd + '/ports']
CPPDEFINES = ['CPU_MIMXRT1062DVL6A', 'SKIP_SYSCLK_INIT', 'EVK_MCIMXRM', 'FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL=1','XIP_EXTERNAL_FLASH=1', 'XIP_BOOT_HEADER_ENABLE=1', 'FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE=1', 'XIP_BOOT_HEADER_DCD_ENABLE=1', 'DATA_SECTION_IS_CACHEABLE=1']

View File

@ -0,0 +1,132 @@
/*
* Copyright 2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "touchpad.h"
void BOARD_LPI2C_Init(LPI2C_Type *base, uint32_t clkSrc_Hz)
{
lpi2c_master_config_t lpi2cConfig = {0};
/*
* lpi2cConfig.debugEnable = false;
* lpi2cConfig.ignoreAck = false;
* lpi2cConfig.pinConfig = kLPI2C_2PinOpenDrain;
* lpi2cConfig.baudRate_Hz = 100000U;
* lpi2cConfig.busIdleTimeout_ns = 0;
* lpi2cConfig.pinLowTimeout_ns = 0;
* lpi2cConfig.sdaGlitchFilterWidth_ns = 0;
* lpi2cConfig.sclGlitchFilterWidth_ns = 0;
*/
LPI2C_MasterGetDefaultConfig(&lpi2cConfig);
LPI2C_MasterInit(base, &lpi2cConfig, clkSrc_Hz);
}
status_t BOARD_LPI2C_Send(LPI2C_Type *base,
uint8_t deviceAddress,
uint32_t subAddress,
uint8_t subAddressSize,
uint8_t *txBuff,
uint8_t txBuffSize)
{
lpi2c_master_transfer_t xfer;
xfer.flags = kLPI2C_TransferDefaultFlag;
xfer.slaveAddress = deviceAddress;
xfer.direction = kLPI2C_Write;
xfer.subaddress = subAddress;
xfer.subaddressSize = subAddressSize;
xfer.data = txBuff;
xfer.dataSize = txBuffSize;
return LPI2C_MasterTransferBlocking(base, &xfer);
}
status_t BOARD_LPI2C_Receive(LPI2C_Type *base,
uint8_t deviceAddress,
uint32_t subAddress,
uint8_t subAddressSize,
uint8_t *rxBuff,
uint8_t rxBuffSize)
{
lpi2c_master_transfer_t xfer;
xfer.flags = kLPI2C_TransferDefaultFlag;
xfer.slaveAddress = deviceAddress;
xfer.direction = kLPI2C_Read;
xfer.subaddress = subAddress;
xfer.subaddressSize = subAddressSize;
xfer.data = rxBuff;
xfer.dataSize = rxBuffSize;
return LPI2C_MasterTransferBlocking(base, &xfer);
}
status_t BOARD_LPI2C_SendSCCB(LPI2C_Type *base,
uint8_t deviceAddress,
uint32_t subAddress,
uint8_t subAddressSize,
uint8_t *txBuff,
uint8_t txBuffSize)
{
lpi2c_master_transfer_t xfer;
xfer.flags = kLPI2C_TransferDefaultFlag;
xfer.slaveAddress = deviceAddress;
xfer.direction = kLPI2C_Write;
xfer.subaddress = subAddress;
xfer.subaddressSize = subAddressSize;
xfer.data = txBuff;
xfer.dataSize = txBuffSize;
return LPI2C_MasterTransferBlocking(base, &xfer);
}
status_t BOARD_LPI2C_ReceiveSCCB(LPI2C_Type *base,
uint8_t deviceAddress,
uint32_t subAddress,
uint8_t subAddressSize,
uint8_t *rxBuff,
uint8_t rxBuffSize)
{
status_t status;
lpi2c_master_transfer_t xfer;
xfer.flags = kLPI2C_TransferDefaultFlag;
xfer.slaveAddress = deviceAddress;
xfer.direction = kLPI2C_Write;
xfer.subaddress = subAddress;
xfer.subaddressSize = subAddressSize;
xfer.data = NULL;
xfer.dataSize = 0;
status = LPI2C_MasterTransferBlocking(base, &xfer);
if (kStatus_Success == status)
{
xfer.subaddressSize = 0;
xfer.direction = kLPI2C_Read;
xfer.data = rxBuff;
xfer.dataSize = rxBuffSize;
status = LPI2C_MasterTransferBlocking(base, &xfer);
}
return status;
}
status_t BOARD_Touch_I2C_Send(
uint8_t deviceAddress, uint32_t subAddress, uint8_t subAddressSize, const uint8_t *txBuff, uint8_t txBuffSize)
{
return BOARD_LPI2C_Send(BOARD_TOUCH_I2C_BASEADDR, deviceAddress, subAddress, subAddressSize, (uint8_t *)txBuff,
txBuffSize);
}
status_t BOARD_Touch_I2C_Receive(
uint8_t deviceAddress, uint32_t subAddress, uint8_t subAddressSize, uint8_t *rxBuff, uint8_t rxBuffSize)
{
return BOARD_LPI2C_Receive(BOARD_TOUCH_I2C_BASEADDR, deviceAddress, subAddress, subAddressSize, rxBuff, rxBuffSize);
}

View File

@ -0,0 +1,61 @@
/*
* Copyright 2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __TOUCHPAD_PORT_H__
#define __TOUCHPAD_PORT_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "fsl_common.h"
#include "clock_config.h"
#include "fsl_lpi2c.h"
#include "fsl_gpio.h"
/* @Brief Board touch panel configuration */
#define BOARD_TOUCH_I2C_BASEADDR LPI2C1
#define BOARD_TOUCH_RST_GPIO GPIO1
#define BOARD_TOUCH_RST_PIN 2
#define BOARD_TOUCH_INT_GPIO GPIO1
#define BOARD_TOUCH_INT_PIN 11
void BOARD_LPI2C_Init(LPI2C_Type *base, uint32_t clkSrc_Hz);
status_t BOARD_LPI2C_Send(LPI2C_Type *base,
uint8_t deviceAddress,
uint32_t subAddress,
uint8_t subaddressSize,
uint8_t *txBuff,
uint8_t txBuffSize);
status_t BOARD_LPI2C_Receive(LPI2C_Type *base,
uint8_t deviceAddress,
uint32_t subAddress,
uint8_t subaddressSize,
uint8_t *rxBuff,
uint8_t rxBuffSize);
status_t BOARD_LPI2C_SendSCCB(LPI2C_Type *base,
uint8_t deviceAddress,
uint32_t subAddress,
uint8_t subaddressSize,
uint8_t *txBuff,
uint8_t txBuffSize);
status_t BOARD_LPI2C_ReceiveSCCB(LPI2C_Type *base,
uint8_t deviceAddress,
uint32_t subAddress,
uint8_t subaddressSize,
uint8_t *rxBuff,
uint8_t rxBuffSize);
status_t BOARD_Touch_I2C_Send(
uint8_t deviceAddress, uint32_t subAddress, uint8_t subAddressSize, const uint8_t *txBuff, uint8_t txBuffSize);
status_t BOARD_Touch_I2C_Receive(
uint8_t deviceAddress, uint32_t subAddress, uint8_t subAddressSize, uint8_t *rxBuff, uint8_t rxBuffSize);
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif

View File

@ -0,0 +1,182 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2019 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_common.h"
#include "fsl_lpi2c.h"
#include "fsl_ft5406_rt.h"
typedef struct _ft5406_rt_touch_point
{
uint8_t XH;
uint8_t XL;
uint8_t YH;
uint8_t YL;
uint8_t RESERVED[2];
} ft5406_rt_touch_point_t;
typedef struct _ft5406_rt_touch_data
{
uint8_t GEST_ID;
uint8_t TD_STATUS;
ft5406_rt_touch_point_t TOUCH[FT5406_RT_MAX_TOUCHES];
} ft5406_rt_touch_data_t;
#define TOUCH_POINT_GET_EVENT(T) ((touch_event_t)((T).XH >> 6))
#define TOUCH_POINT_GET_ID(T) ((T).YH >> 4)
#define TOUCH_POINT_GET_X(T) ((((T).XH & 0x0f) << 8) | (T).XL)
#define TOUCH_POINT_GET_Y(T) ((((T).YH & 0x0f) << 8) | (T).YL)
status_t FT5406_RT_Init(ft5406_rt_handle_t *handle, LPI2C_Type *base)
{
lpi2c_master_transfer_t *xfer = &(handle->xfer);
status_t status;
uint8_t mode;
assert(handle);
assert(base);
if (!handle || !base)
{
return kStatus_InvalidArgument;
}
handle->base = base;
/* clear transfer structure and buffer */
memset(xfer, 0, sizeof(*xfer));
memset(handle->touch_buf, 0, FT5406_RT_TOUCH_DATA_LEN);
/* set device mode to normal operation */
mode = 0;
xfer->slaveAddress = FT5406_RT_I2C_ADDRESS;
xfer->direction = kLPI2C_Write;
xfer->subaddress = 0;
xfer->subaddressSize = 1;
xfer->data = &mode;
xfer->dataSize = 1;
xfer->flags = kLPI2C_TransferDefaultFlag;
status = LPI2C_MasterTransferBlocking(handle->base, &handle->xfer);
/* prepare transfer structure for reading touch data */
xfer->slaveAddress = FT5406_RT_I2C_ADDRESS;
xfer->direction = kLPI2C_Read;
xfer->subaddress = 1;
xfer->subaddressSize = 1;
xfer->data = handle->touch_buf;
xfer->dataSize = FT5406_RT_TOUCH_DATA_LEN;
xfer->flags = kLPI2C_TransferDefaultFlag;
return status;
}
status_t FT5406_RT_Denit(ft5406_rt_handle_t *handle)
{
assert(handle);
if (!handle)
{
return kStatus_InvalidArgument;
}
handle->base = NULL;
return kStatus_Success;
}
status_t FT5406_RT_ReadTouchData(ft5406_rt_handle_t *handle)
{
assert(handle);
if (!handle)
{
return kStatus_InvalidArgument;
}
return LPI2C_MasterTransferBlocking(handle->base, &handle->xfer);
}
status_t FT5406_RT_GetSingleTouch(ft5406_rt_handle_t *handle, touch_event_t *touch_event, int *touch_x, int *touch_y)
{
status_t status;
touch_event_t touch_event_local;
status = FT5406_RT_ReadTouchData(handle);
if (status == kStatus_Success)
{
ft5406_rt_touch_data_t *touch_data = (ft5406_rt_touch_data_t *)(void *)(handle->touch_buf);
if (touch_event == NULL)
{
touch_event = &touch_event_local;
}
*touch_event = TOUCH_POINT_GET_EVENT(touch_data->TOUCH[0]);
/* Update coordinates only if there is touch detected */
if ((*touch_event == kTouch_Down) || (*touch_event == kTouch_Contact))
{
if (touch_x)
{
*touch_x = TOUCH_POINT_GET_X(touch_data->TOUCH[0]);
}
if (touch_y)
{
*touch_y = TOUCH_POINT_GET_Y(touch_data->TOUCH[0]);
}
}
}
return status;
}
status_t FT5406_RT_GetMultiTouch(ft5406_rt_handle_t *handle,
int *touch_count,
touch_point_t touch_array[FT5406_RT_MAX_TOUCHES])
{
status_t status;
status = FT5406_RT_ReadTouchData(handle);
if (status == kStatus_Success)
{
ft5406_rt_touch_data_t *touch_data = (ft5406_rt_touch_data_t *)(void *)(handle->touch_buf);
int i;
/* Check for valid number of touches - otherwise ignore touch information */
if (touch_data->TD_STATUS > FT5406_RT_MAX_TOUCHES)
{
touch_data->TD_STATUS = 0;
}
/* Decode number of touches */
if (touch_count)
{
*touch_count = touch_data->TD_STATUS;
}
/* Decode valid touch points */
for (i = 0; i < touch_data->TD_STATUS; i++)
{
touch_array[i].TOUCH_ID = TOUCH_POINT_GET_ID(touch_data->TOUCH[i]);
touch_array[i].TOUCH_EVENT = TOUCH_POINT_GET_EVENT(touch_data->TOUCH[i]);
touch_array[i].TOUCH_X = TOUCH_POINT_GET_X(touch_data->TOUCH[i]);
touch_array[i].TOUCH_Y = TOUCH_POINT_GET_Y(touch_data->TOUCH[i]);
}
/* Clear vacant elements of touch_array */
for (; i < FT5406_RT_MAX_TOUCHES; i++)
{
touch_array[i].TOUCH_ID = 0;
touch_array[i].TOUCH_EVENT = kTouch_Reserved;
touch_array[i].TOUCH_X = 0;
touch_array[i].TOUCH_Y = 0;
}
}
return status;
}

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_FT5406_RT_H_
#define _FSL_FT5406_RT_H_
#include "fsl_common.h"
/*!
* @addtogroup ft5406_rt
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief FT5406_RT I2C address. */
#define FT5406_RT_I2C_ADDRESS (0x38)
/*! @brief FT5406_RT maximum number of simultaneously detected touches. */
#define FT5406_RT_MAX_TOUCHES (5U)
/*! @brief FT5406_RT register address where touch data begin. */
#define FT5406_RT_TOUCH_DATA_SUBADDR (1)
/*! @brief FT5406_RT raw touch data length. */
#define FT5406_RT_TOUCH_DATA_LEN (0x20)
typedef enum _touch_event
{
kTouch_Down = 0, /*!< The state changed to touched. */
kTouch_Up = 1, /*!< The state changed to not touched. */
kTouch_Contact = 2, /*!< There is a continuous touch being detected. */
kTouch_Reserved = 3 /*!< No touch information available. */
} touch_event_t;
typedef struct _touch_point
{
touch_event_t TOUCH_EVENT; /*!< Indicates the state or event of the touch point. */
uint8_t TOUCH_ID; /*!< Id of the touch point. This numeric value stays constant between down and up event. */
uint16_t TOUCH_X; /*!< X coordinate of the touch point */
uint16_t TOUCH_Y; /*!< Y coordinate of the touch point */
} touch_point_t;
typedef struct _ft5406_rt_handle
{
LPI2C_Type *base;
lpi2c_master_transfer_t xfer;
uint8_t touch_buf[FT5406_RT_TOUCH_DATA_LEN];
} ft5406_rt_handle_t;
status_t FT5406_RT_Init(ft5406_rt_handle_t *handle, LPI2C_Type *base);
status_t FT5406_RT_Denit(ft5406_rt_handle_t *handle);
status_t FT5406_RT_GetSingleTouch(ft5406_rt_handle_t *handle, touch_event_t *touch_event, int *touch_x, int *touch_y);
status_t FT5406_RT_GetMultiTouch(ft5406_rt_handle_t *handle,
int *touch_count,
touch_point_t touch_array[FT5406_RT_MAX_TOUCHES]);
#endif

View File

@ -0,0 +1,317 @@
/*
* Copyright 2019-2020 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_gt911.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief GT911 I2C address. */
#define GT911_I2C_ADDRESS0 (0x5D)
#define GT911_I2C_ADDRESS1 (0x14)
#define GT911_REG_ADDR_SIZE 2
/*! @brief GT911 registers. */
#define GT911_REG_ID 0x8140U
#define GT911_CONFIG_ADDR 0x8047U
#define GT911_REG_XL 0x8048U
#define GT911_REG_XH 0x8049U
#define GT911_REG_YL 0x804AU
#define GT911_REG_YH 0x804BU
#define GT911_REG_TOUCH_NUM 0x804CU
#define GT911_REG_CONFIG_VERSION 0x8047U
#define GT911_REG_MODULE_SWITCH1 0x804DU
#define GT911_REG_STAT 0x814EU
#define GT911_REG_FIRST_POINT 0x814FU
#define GT911_STAT_BUF_MASK (1U << 7U)
#define GT911_STAT_POINT_NUMBER_MASK (0xFU << 0U)
#define GT911_MODULE_SWITCH_X2Y_MASK (1U << 3U)
#define GT911_MODULE_SWITCH_INT_MASK (3U << 0U)
#define GT911_CONFIG_SIZE (186U)
/*******************************************************************************
* Prototypes
******************************************************************************/
/* Verify firmware, return true if pass. */
static bool GT911_VerifyFirmware(const uint8_t *firmware);
static uint8_t GT911_GetFirmwareCheckSum(const uint8_t *firmware);
/*******************************************************************************
* Variables
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
static uint8_t GT911_GetFirmwareCheckSum(const uint8_t *firmware)
{
uint8_t sum = 0;
uint16_t i = 0;
for (i = 0; i < GT911_CONFIG_SIZE - 2U; i++)
{
sum += (*firmware);
firmware++;
}
return (~sum + 1U);
}
static bool GT911_VerifyFirmware(const uint8_t *firmware)
{
return ((firmware[GT911_REG_CONFIG_VERSION - GT911_CONFIG_ADDR] != 0U) &&
(GT911_GetFirmwareCheckSum(firmware) == firmware[GT911_CONFIG_SIZE - 2U]));
}
status_t GT911_Init(gt911_handle_t *handle, const gt911_config_t *config)
{
status_t status;
uint32_t deviceID;
uint8_t gt911Config[GT911_CONFIG_SIZE];
assert(NULL != handle);
(void)memset(handle, 0, sizeof(*handle));
handle->I2C_SendFunc = config->I2C_SendFunc;
handle->I2C_ReceiveFunc = config->I2C_ReceiveFunc;
handle->timeDelayMsFunc = config->timeDelayMsFunc;
handle->pullResetPinFunc = config->pullResetPinFunc;
/* Reset the panel and set the I2C address mode. */
config->intPinFunc(kGT911_IntPinPullDown);
config->pullResetPinFunc(false);
/* >= 10ms. */
handle->timeDelayMsFunc(20);
if (kGT911_I2cAddrAny == config->i2cAddrMode)
{
config->pullResetPinFunc(true);
/* >= 55ms */
handle->timeDelayMsFunc(55);
config->intPinFunc(kGT911_IntPinInput);
/* Try address 0 */
handle->i2cAddr = GT911_I2C_ADDRESS0;
status = handle->I2C_ReceiveFunc(handle->i2cAddr, GT911_REG_ID, GT911_REG_ADDR_SIZE, (uint8_t *)&deviceID, 4);
if (kStatus_Success != status)
{
/* Try address 1 */
handle->i2cAddr = GT911_I2C_ADDRESS1;
status =
handle->I2C_ReceiveFunc(handle->i2cAddr, GT911_REG_ID, GT911_REG_ADDR_SIZE, (uint8_t *)&deviceID, 4);
if (kStatus_Success != status)
{
return status;
}
}
}
else
{
if (kGT911_I2cAddrMode1 == config->i2cAddrMode)
{
config->intPinFunc(kGT911_IntPinPullUp);
handle->i2cAddr = GT911_I2C_ADDRESS1;
}
else
{
handle->i2cAddr = GT911_I2C_ADDRESS0;
}
/* >= 100us */
handle->timeDelayMsFunc(1);
config->pullResetPinFunc(true);
/* >= 5ms */
handle->timeDelayMsFunc(5);
config->intPinFunc(kGT911_IntPinPullDown);
/* >= 50ms */
handle->timeDelayMsFunc(50);
config->intPinFunc(kGT911_IntPinInput);
status = handle->I2C_ReceiveFunc(handle->i2cAddr, GT911_REG_ID, GT911_REG_ADDR_SIZE, (uint8_t *)&deviceID, 4);
if (kStatus_Success != status)
{
return status;
}
}
/* Verify the device. */
if (deviceID != 0x00313139U)
{
return kStatus_Fail;
}
/* Initialize the IC. */
status = handle->I2C_ReceiveFunc(handle->i2cAddr, GT911_CONFIG_ADDR, GT911_REG_ADDR_SIZE, gt911Config,
GT911_CONFIG_SIZE);
if (kStatus_Success != status)
{
return status;
}
/*
* GT911 driver gets the original firmware from touch panel control IC, modify
* the configuration, then set it to the IC again. The original firmware
* read from the touch IC must be correct, otherwise setting wrong firmware
* to the touch IC will break it.
*/
if (true != GT911_VerifyFirmware(gt911Config))
{
return kStatus_Fail;
}
handle->resolutionX = ((uint16_t)gt911Config[GT911_REG_XH - GT911_CONFIG_ADDR]) << 8U;
handle->resolutionX += gt911Config[GT911_REG_XL - GT911_CONFIG_ADDR];
handle->resolutionY = ((uint16_t)gt911Config[GT911_REG_YH - GT911_CONFIG_ADDR]) << 8U;
handle->resolutionY += gt911Config[GT911_REG_YL - GT911_CONFIG_ADDR];
gt911Config[GT911_REG_TOUCH_NUM - GT911_CONFIG_ADDR] = (config->touchPointNum) & 0x0FU;
gt911Config[GT911_REG_MODULE_SWITCH1 - GT911_CONFIG_ADDR] &= (uint8_t)(~GT911_MODULE_SWITCH_INT_MASK);
gt911Config[GT911_REG_MODULE_SWITCH1 - GT911_CONFIG_ADDR] |= (uint8_t)(config->intTrigMode);
gt911Config[GT911_CONFIG_SIZE - 2U] = GT911_GetFirmwareCheckSum(gt911Config);
gt911Config[GT911_CONFIG_SIZE - 1U] = 1U; /* Mark the firmware as valid. */
return handle->I2C_SendFunc(handle->i2cAddr, GT911_CONFIG_ADDR, GT911_REG_ADDR_SIZE, gt911Config,
GT911_CONFIG_SIZE);
}
status_t GT911_Deinit(gt911_handle_t *handle)
{
handle->pullResetPinFunc(false);
return kStatus_Success;
}
static status_t GT911_ReadRawTouchData(gt911_handle_t *handle, uint8_t *touchPointNum)
{
status_t status;
uint8_t gt911Stat;
status = handle->I2C_ReceiveFunc(handle->i2cAddr, GT911_REG_STAT, GT911_REG_ADDR_SIZE, &gt911Stat, 1);
if (kStatus_Success != status)
{
*touchPointNum = 0;
return status;
}
*touchPointNum = gt911Stat & GT911_STAT_POINT_NUMBER_MASK;
if (0U != (gt911Stat & GT911_STAT_BUF_MASK))
{
if (*touchPointNum > 0U)
{
status = handle->I2C_ReceiveFunc(handle->i2cAddr, GT911_REG_FIRST_POINT, GT911_REG_ADDR_SIZE,
(void *)handle->pointReg, (*touchPointNum) * sizeof(gt911_point_reg_t));
}
/* Must set the status register to 0 after read. */
gt911Stat = 0;
status = handle->I2C_SendFunc(handle->i2cAddr, GT911_REG_STAT, GT911_REG_ADDR_SIZE, &gt911Stat, 1);
}
return status;
}
status_t GT911_GetSingleTouch(gt911_handle_t *handle, int *touch_x, int *touch_y)
{
status_t status;
uint8_t touchPointNum;
status = GT911_ReadRawTouchData(handle, &touchPointNum);
if (kStatus_Success == status)
{
if (touchPointNum > 0U)
{
*touch_x =
(int)(uint16_t)((uint16_t)handle->pointReg[0].lowX + (((uint16_t)handle->pointReg[0].highX) << 8U));
*touch_y =
(int)(uint16_t)((uint16_t)handle->pointReg[0].lowY + (((uint16_t)handle->pointReg[0].highY) << 8U));
}
else
{
status = (status_t)kStatus_TOUCHPANEL_NotTouched;
}
}
else
{
status = kStatus_Fail;
}
return status;
}
status_t GT911_GetMultiTouch(gt911_handle_t *handle, uint8_t *touch_count, touch_point_t touch_array[])
{
status_t status;
uint32_t i;
uint8_t desiredTouchPointNum;
uint8_t actualTouchPointNum;
status = GT911_ReadRawTouchData(handle, &actualTouchPointNum);
if (kStatus_Success == status)
{
desiredTouchPointNum = *touch_count;
if (0U == actualTouchPointNum)
{
status = (status_t)kStatus_TOUCHPANEL_NotTouched;
}
else if (actualTouchPointNum > desiredTouchPointNum)
{
actualTouchPointNum = desiredTouchPointNum;
}
else
{
/* MISRA compatible. */
}
for (i = 0; i < actualTouchPointNum; i++)
{
touch_array[i].valid = true;
touch_array[i].touchID = handle->pointReg[i].id;
touch_array[i].x = handle->pointReg[i].lowX + (((uint16_t)handle->pointReg[i].highX) << 8U);
touch_array[i].y = handle->pointReg[i].lowY + (((uint16_t)handle->pointReg[i].highY) << 8U);
}
for (; i < desiredTouchPointNum; i++)
{
touch_array[i].valid = false;
}
}
else
{
status = kStatus_Fail;
}
*touch_count = actualTouchPointNum;
return status;
}
status_t GT911_GetResolution(gt911_handle_t *handle, int *resolutionX, int *resolutionY)
{
*resolutionX = (int)handle->resolutionX;
*resolutionY = (int)handle->resolutionY;
return kStatus_Success;
}

View File

@ -0,0 +1,198 @@
/*
* Copyright 2019-2020 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_GT911_H_
#define _FSL_GT911_H_
#include "fsl_common.h"
/*
* Change Log:
*
* 1.0.3:
* - Fixed MISRA 2012 issues.
*
* 1.0.2:
* - Fixed the issue that INT pin is output low when using kGT911_I2cAddrAny.
*
* 1.0.1:
* - Update GT911_GetMultiTouch and GT911_GetSingleTouch to return
* kStatus_TOUCHPANEL_NotTouched when no touch happens.
*
* 1.0.0:
* - Initial version.
*/
/*!
* @addtogroup gt911
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief GT911 maximum number of simultaneously detected touches. */
#define GT911_MAX_TOUCHES (10U)
/*! @brief Error code definition. */
enum _touch_status
{
kStatus_TOUCHPANEL_NotTouched = MAKE_STATUS(kStatusGroup_TOUCH_PANEL, 0) /*!< No touch happen. */
};
/*! @brief Touch point definition. */
typedef struct
{
bool valid; /*!< Whether the touch point coordinate value is valid. */
uint8_t touchID; /*!< Id of the touch point. This numeric value stays constant between down and up event. */
uint16_t x; /*!< X coordinate of the touch point */
uint16_t y; /*!< Y coordinate of the touch point */
} touch_point_t;
/*! @brief gt911 I2C address mode.*/
typedef enum _gt911_i2c_addr_mode
{
kGT911_I2cAddrMode0, /*!< 7-bit address 0x5D, or 8-bit 0xBA/0xBB */
kGT911_I2cAddrMode1, /*!< 7-bit address 0x14, or 8-bit 0x28/0x29 */
kGT911_I2cAddrAny, /*!< Use 0x5D or 0x14, driver selects the right one to use,
this is used for the case that MCU could not pull
the INT pin level.
*/
} gt911_i2c_addr_mode_t;
/*! @brief gt911 interrupt pin mode.*/
typedef enum _gt911_int_pin_mode
{
kGT911_IntPinPullDown, /*!< Interrupt pin output pull down. */
kGT911_IntPinPullUp, /*!< Interrupt pin output pull up. */
kGT911_IntPinInput, /*!< Interrupt pin set to input mode. */
} gt911_int_pin_mode_t;
/*! @brief gt911 interrupt trigger mode.*/
typedef enum _gt911_int_trig_mode
{
kGT911_IntRisingEdge, /*!< Rising edge. */
kGT911_IntFallingEdge, /*!< Falling edge. */
kGT911_IntLowLevel, /*!< Low level. */
kGT911_IntHighLevel, /*!< High edge. */
} gt911_int_trig_mode_t;
typedef status_t (*gt911_i2c_send_func_t)(
uint8_t deviceAddress, uint32_t subAddress, uint8_t subaddressSize, const uint8_t *txBuff, uint8_t txBuffSize);
typedef status_t (*gt911_i2c_receive_func_t)(
uint8_t deviceAddress, uint32_t subAddress, uint8_t subaddressSize, uint8_t *rxBuff, uint8_t rxBuffSize);
typedef void (*gt911_int_pin_func_t)(gt911_int_pin_mode_t mode);
typedef void (*gt911_reset_pin_func_t)(bool pullUp);
/*! @brief gt911 configure structure.*/
typedef struct _gt911_point_reg
{
uint8_t id; /*!< Track ID. */
uint8_t lowX; /*!< Low byte of x coordinate. */
uint8_t highX; /*!< High byte of x coordinate. */
uint8_t lowY; /*!< Low byte of y coordinate. */
uint8_t highY; /*!< High byte of x coordinate. */
uint8_t lowSize; /*!< Low byte of point size. */
uint8_t highSize; /*!< High byte of point size. */
uint8_t reserved; /*!< Reserved. */
} gt911_point_reg_t;
/*! @brief gt911 configure structure.*/
typedef struct _gt911_config
{
gt911_i2c_send_func_t I2C_SendFunc; /*!< Function to send I2C data. */
gt911_i2c_receive_func_t I2C_ReceiveFunc; /*!< Function to receive I2C data. */
void (*timeDelayMsFunc)(uint32_t delayMs); /*!< Function to delay some MS. */
gt911_int_pin_func_t intPinFunc; /*!< Function to set interrupt pin to different mode. */
gt911_reset_pin_func_t pullResetPinFunc; /*!< Function to pull reset pin high or low. */
uint8_t touchPointNum; /*!< How many touch points to enable. */
gt911_i2c_addr_mode_t i2cAddrMode; /*!< I2C address mode. */
gt911_int_trig_mode_t intTrigMode; /*!< Interrupt trigger mode. */
} gt911_config_t;
/*! @brief gt911 driver structure.*/
typedef struct _gt911_handle
{
gt911_i2c_send_func_t I2C_SendFunc; /*!< Function to send I2C data. */
gt911_i2c_receive_func_t I2C_ReceiveFunc; /*!< Function to receive I2C data. */
void (*timeDelayMsFunc)(uint32_t delayMs); /*!< Function to delay some MS. */
gt911_reset_pin_func_t pullResetPinFunc; /*!< Function to pull reset pin high or low. */
gt911_point_reg_t pointReg[GT911_MAX_TOUCHES]; /*!< Buffer to receive touch point raw data. */
uint8_t touchPointNum; /*!< How many touch points to enable. */
uint8_t i2cAddr; /*!< I2C address. */
uint16_t resolutionX; /*!< Resolution. */
uint16_t resolutionY; /*!< Resolution. */
} gt911_handle_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @brief Initialize the driver.
*
* @param[in] handle Pointer to the GT911 driver.
* @param[in] config Pointer to the configuration.
* @return Returns @ref kStatus_Success if succeeded, otherwise return error code.
*/
status_t GT911_Init(gt911_handle_t *handle, const gt911_config_t *config);
/*!
* @brief De-initialize the driver.
*
* @param[in] handle Pointer to the GT911 driver.
* @return Returns @ref kStatus_Success if succeeded, otherwise return error code.
*/
status_t GT911_Deinit(gt911_handle_t *handle);
/*!
* @brief Get single touch point coordinate.
*
* @param[in] handle Pointer to the GT911 driver.
* @param[out] touch_x X coordinate of the touch point.
* @param[out] touch_y Y coordinate of the touch point.
* @return Returns @ref kStatus_Success if succeeded, otherwise return error code.
*/
status_t GT911_GetSingleTouch(gt911_handle_t *handle, int *touch_x, int *touch_y);
/*!
* @brief Get multiple touch points coordinate.
*
* When calling this function, parameter @ref touch_count means the array size
* of @p touch_array. After the function returns, the @p touch_count means how
* many valid touch points there are in the @p touch_array.
*
* @param[in] handle Pointer to the GT911 driver.
* @param[in, out] touch_count The touch point number.
* @param[out] touch_array Array of touch points coordinate.
* @return Returns @ref kStatus_Success if succeeded, otherwise return error code.
*/
status_t GT911_GetMultiTouch(gt911_handle_t *handle, uint8_t *touch_count, touch_point_t touch_array[]);
/*!
* @brief Get touch IC resolution.
*
* Note the touch resolution might be different with display resolution.
*
* @param handle Pointer to the driver.
* @param touch_x X resolution.
* @param touch_y Y resolution.
* @return Returns @ref kStatus_Success if succeeded, otherwise return error code.
*/
status_t GT911_GetResolution(gt911_handle_t *handle, int *resolutionX, int *resolutionY);
#if defined(__cplusplus)
}
#endif
/*! @} */
#endif /* _FSL_GT911_H_ */

View File

@ -0,0 +1,259 @@
/*
* Copyright 2017, 2020-2021 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_video_common.h"
#if defined(SDK_OS_FREE_RTOS)
#include "FreeRTOS.h"
#include "task.h"
#endif
/*******************************************************************************
* Code
******************************************************************************/
bool VIDEO_IsYUV(video_pixel_format_t format)
{
if ((kVIDEO_PixelFormatYUYV == format) || (kVIDEO_PixelFormatYVYU == format) ||
(kVIDEO_PixelFormatUYVY == format) || (kVIDEO_PixelFormatVYUY == format) ||
(kVIDEO_PixelFormatXYVU == format) || (kVIDEO_PixelFormatXYUV == format))
{
return true;
}
else
{
return false;
}
}
void VIDEO_DelayMs(uint32_t ms)
{
#if defined(SDK_OS_FREE_RTOS)
TickType_t tick;
tick = ms * configTICK_RATE_HZ / 1000U;
tick = (0U == tick) ? 1U : tick;
vTaskDelay(tick);
#else
while (0U != (ms--))
{
SDK_DelayAtLeastUs(1000U, SystemCoreClock);
}
#endif
}
uint8_t VIDEO_GetPixelSizeBits(video_pixel_format_t pixelFormat)
{
uint8_t ret;
switch (pixelFormat)
{
case kVIDEO_PixelFormatXRGB8888:
case kVIDEO_PixelFormatRGBX8888:
case kVIDEO_PixelFormatXBGR8888:
case kVIDEO_PixelFormatBGRX8888:
case kVIDEO_PixelFormatXYUV:
case kVIDEO_PixelFormatXYVU:
ret = 32;
break;
case kVIDEO_PixelFormatRGB888:
case kVIDEO_PixelFormatBGR888:
ret = 24;
break;
case kVIDEO_PixelFormatRGB565:
case kVIDEO_PixelFormatBGR565:
case kVIDEO_PixelFormatXRGB1555:
case kVIDEO_PixelFormatRGBX5551:
case kVIDEO_PixelFormatXBGR1555:
case kVIDEO_PixelFormatBGRX5551:
case kVIDEO_PixelFormatXRGB4444:
case kVIDEO_PixelFormatRGBX4444:
case kVIDEO_PixelFormatXBGR4444:
case kVIDEO_PixelFormatBGRX4444:
case kVIDEO_PixelFormatYUYV:
case kVIDEO_PixelFormatYVYU:
case kVIDEO_PixelFormatUYVY:
case kVIDEO_PixelFormatVYUY:
ret = 16;
break;
default:
ret = 0;
break;
}
return ret;
}
status_t VIDEO_RINGBUF_Init(video_ringbuf_t *ringbuf, void **buf, uint32_t size)
{
assert(ringbuf);
ringbuf->rear = 0;
ringbuf->front = 0;
ringbuf->size = size;
ringbuf->buf = buf;
return kStatus_Success;
}
status_t VIDEO_RINGBUF_Get(video_ringbuf_t *ringbuf, void **item)
{
uint32_t front_next;
/* To fix IAR Pa082 warning. */
uint32_t rear = ringbuf->rear;
uint32_t front = ringbuf->front;
if (rear != front)
{
*item = ringbuf->buf[ringbuf->front];
/*
* Here don't use ringbuf->front = (ringbuf->front + 1) % ringbuf->size,
* because mod operation might be slow.
*/
front_next = (ringbuf->front + 1U);
/* Use two steps to make sure ringbuf->front is always a valid value. */
ringbuf->front = (front_next == ringbuf->size) ? 0UL : front_next;
return kStatus_Success;
}
else
{
return kStatus_Fail;
}
}
status_t VIDEO_RINGBUF_Put(video_ringbuf_t *ringbuf, void *item)
{
/*
* Here don't use ringbuf->rear = (ringbuf->rear + 1) % ringbuf->size,
* because mod operation might be slow.
*/
uint32_t rear_next = ringbuf->rear + 1U;
rear_next = (rear_next == ringbuf->size) ? 0U : rear_next;
if (rear_next != ringbuf->front)
{
ringbuf->buf[ringbuf->rear] = item;
ringbuf->rear = rear_next;
return kStatus_Success;
}
/* No room. */
else
{
return kStatus_Fail;
}
}
uint32_t VIDEO_RINGBUF_GetLength(video_ringbuf_t *ringbuf)
{
uint32_t ret;
/* To fix IAR Pa082 warning. */
uint32_t rear = ringbuf->rear;
uint32_t front = ringbuf->front;
ret = (rear + ringbuf->size) - front;
if (ret >= ringbuf->size)
{
ret -= ringbuf->size;
}
return ret;
}
bool VIDEO_RINGBUF_IsEmpty(video_ringbuf_t *ringbuf)
{
/* To fix IAR Pa082 warning. */
uint32_t rear = ringbuf->rear;
uint32_t front = ringbuf->front;
if (rear == front)
{
return true;
}
else
{
return false;
}
}
bool VIDEO_RINGBUF_IsFull(video_ringbuf_t *ringbuf)
{
uint32_t rear = ringbuf->rear;
uint32_t front = ringbuf->front;
rear++;
if (rear >= ringbuf->size)
{
rear = 0;
}
if (rear == front)
{
return true;
}
else
{
return false;
}
}
status_t VIDEO_MEMPOOL_Init(video_mempool_t *mempool, void *initMem, uint32_t size, uint32_t count)
{
(void)memset(mempool, 0, sizeof(video_mempool_t));
while (0U != (count--))
{
VIDEO_MEMPOOL_Put(mempool, initMem);
initMem = &((uint8_t *)initMem)[size];
}
return kStatus_Success;
}
void VIDEO_MEMPOOL_InitEmpty(video_mempool_t *mempool)
{
mempool->pool = NULL;
mempool->cnt = 0;
}
void VIDEO_MEMPOOL_Put(video_mempool_t *mempool, void *mem)
{
*(void **)mem = mempool->pool;
mempool->pool = mem;
mempool->cnt++;
}
void *VIDEO_MEMPOOL_Get(video_mempool_t *mempool)
{
void *mem = mempool->pool;
if (NULL != mem)
{
mempool->cnt--;
mempool->pool = *(void **)mem;
}
return mem;
}
uint32_t VIDEO_MEMPOOL_GetCount(video_mempool_t *mempool)
{
return mempool->cnt;
}

View File

@ -0,0 +1,291 @@
/*
* Copyright 2017, 2020-2021 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_VIDEO_COMMON_H_
#define _FSL_VIDEO_COMMON_H_
#include "fsl_common.h"
/*
* Change log:
*
* 1.0.5
* - Fix IAR Pa082 warning.
*
* 1.0.4
* - Add LUT8 definition.
*
* 1.0.3
* - Add RAW8 definition.
*
* 1.0.2
* - Fixed MISRA-C 2012 issues.
*
* 1.0.1
* - Update the VIDEO_DelayMs for bare metal.
*
* 1.0.0
* - Initial version
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Pixel format FOURCC. */
#define FSL_VIDEO_FOURCC(a, b, c, d) \
((uint32_t)(a) | ((uint32_t)(b) << 8U) | ((uint32_t)(c) << 16U) | ((uint32_t)(d) << 24U))
/*! @brief Macro to define resolution. */
#define FSL_VIDEO_RESOLUTION(width, height) ((uint32_t)(width) | ((uint32_t)(height) << 16U))
#define FSL_VIDEO_EXTRACT_WIDTH(resolution) ((uint16_t)((resolution)&0xFFFFU))
#define FSL_VIDEO_EXTRACT_HEIGHT(resolution) ((uint16_t)((resolution) >> 16U))
/*! @brief Pixel format definition. */
typedef enum _video_pixel_format
{
/* RAW */
kVIDEO_PixelFormatRAW8 = FSL_VIDEO_FOURCC('G', 'R', 'B', 'G'), /*!< RAW8, GRBG. */
/* LUT/palette */
kVIDEO_PixelFormatLUT8 = FSL_VIDEO_FOURCC('L', 'U', 'T', '8'), /*!< 8-bit Indexed Color. */
/* RGB */
kVIDEO_PixelFormatXRGB8888 = FSL_VIDEO_FOURCC('X', 'R', '2', '4'), /*!< 32-bit XRGB8888. */
kVIDEO_PixelFormatRGBX8888 = FSL_VIDEO_FOURCC('R', 'X', '2', '4'), /*!< 32-bit RGBX8888. */
kVIDEO_PixelFormatXBGR8888 = FSL_VIDEO_FOURCC('X', 'B', '2', '4'), /*!< 32-bit XBGR8888. */
kVIDEO_PixelFormatBGRX8888 = FSL_VIDEO_FOURCC('B', 'X', '2', '4'), /*!< 32-bit BGRX8888. */
kVIDEO_PixelFormatRGB888 = FSL_VIDEO_FOURCC('R', 'G', '2', '4'), /*!< 24-bit RGB888. */
kVIDEO_PixelFormatBGR888 = FSL_VIDEO_FOURCC('B', 'G', '2', '4'), /*!< 24-bit BGR888. */
kVIDEO_PixelFormatRGB565 = FSL_VIDEO_FOURCC('R', 'G', '1', '6'), /*!< 16-bit RGB565. */
kVIDEO_PixelFormatBGR565 = FSL_VIDEO_FOURCC('B', 'G', '1', '6'), /*!< 16-bit BGR565. */
kVIDEO_PixelFormatXRGB1555 = FSL_VIDEO_FOURCC('X', 'R', '1', '5'), /*!< 16-bit XRGB1555. */
kVIDEO_PixelFormatRGBX5551 = FSL_VIDEO_FOURCC('R', 'X', '1', '5'), /*!< 16-bit RGBX5551. */
kVIDEO_PixelFormatXBGR1555 = FSL_VIDEO_FOURCC('X', 'B', '1', '5'), /*!< 16-bit XBGR1555. */
kVIDEO_PixelFormatBGRX5551 = FSL_VIDEO_FOURCC('B', 'X', '1', '5'), /*!< 16-bit BGRX5551. */
kVIDEO_PixelFormatXRGB4444 = FSL_VIDEO_FOURCC('X', 'R', '1', '2'), /*!< 16-bit XRGB4444. */
kVIDEO_PixelFormatRGBX4444 = FSL_VIDEO_FOURCC('R', 'X', '1', '2'), /*!< 16-bit RGBX4444. */
kVIDEO_PixelFormatXBGR4444 = FSL_VIDEO_FOURCC('X', 'B', '1', '2'), /*!< 16-bit XBGR4444. */
kVIDEO_PixelFormatBGRX4444 = FSL_VIDEO_FOURCC('B', 'X', '1', '2'), /*!< 16-bit BGRX4444. */
/* YUV. */
kVIDEO_PixelFormatYUYV = FSL_VIDEO_FOURCC('Y', 'U', 'Y', 'V'), /*!< YUV422, Y-U-Y-V. */
kVIDEO_PixelFormatYVYU = FSL_VIDEO_FOURCC('Y', 'V', 'Y', 'U'), /*!< YUV422, Y-V-Y-U. */
kVIDEO_PixelFormatUYVY = FSL_VIDEO_FOURCC('U', 'Y', 'V', 'Y'), /*!< YUV422, U-Y-V-Y. */
kVIDEO_PixelFormatVYUY = FSL_VIDEO_FOURCC('V', 'Y', 'U', 'Y'), /*!< YUV422, V-Y-U-Y. */
kVIDEO_PixelFormatXYUV = FSL_VIDEO_FOURCC('X', 'Y', 'U', 'V'), /*!< YUV444, X-Y-U-V. */
kVIDEO_PixelFormatXYVU = FSL_VIDEO_FOURCC('X', 'Y', 'V', 'U'), /*!< YUV444, X-Y-V-U. */
} video_pixel_format_t;
/*! @brief Resolution definition. */
typedef enum _video_resolution
{
kVIDEO_ResolutionVGA = FSL_VIDEO_RESOLUTION(640, 480), /*!< VGA, 640 * 480 */
kVIDEO_ResolutionQVGA = FSL_VIDEO_RESOLUTION(320, 240), /*!< QVGA, 320 * 240 */
kVIDEO_ResolutionQQVGA = FSL_VIDEO_RESOLUTION(160, 120), /*!< QQVGA, 160 * 120 */
kVIDEO_ResolutionCIF = FSL_VIDEO_RESOLUTION(352, 288), /*!< CIF, 352 * 288 */
kVIDEO_ResolutionQCIF = FSL_VIDEO_RESOLUTION(176, 144), /*!< QCIF, 176 * 144 */
kVIDEO_ResolutionQQCIF = FSL_VIDEO_RESOLUTION(88, 72), /*!< QQCIF, 88 * 72 */
kVIDEO_Resolution720P = FSL_VIDEO_RESOLUTION(1280, 720), /*!< 720P, 1280 * 720 */
kVIDEO_Resolution1080P = FSL_VIDEO_RESOLUTION(1920, 1080), /*!< 1080P, 1920 * 1280*/
kVIDEO_ResolutionWXGA = FSL_VIDEO_RESOLUTION(1280, 800), /*!< WXGA, 1280 * 800 */
} video_resolution_t;
/*!
* @brief Ring buffer structure.
*
* There is one empty room reserved in the ring buffer, used to distinguish
* whether the ring buffer is full or empty. When rear equals front, it is empty;
* when rear+1 equals front, it is full.
*/
typedef struct
{
volatile uint32_t rear; /*!< Pointer to save the incoming item. */
volatile uint32_t front; /*!< Pointer to read out the item. */
void *volatile *buf; /*!< Memory to the ring buffer. */
uint32_t size; /*!< Ring buffer total size. */
} video_ringbuf_t;
/*!
* @brief Memory pool structure.
*/
typedef struct
{
void *volatile pool; /*!< Pointer to the pool. */
volatile uint32_t cnt; /*!< Count of memory blocks in the pool. */
} video_mempool_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Common
* @{
*/
/*!
* @brief Check the pixel format is YUV or not.
*
* @param format Pixel format.
*/
bool VIDEO_IsYUV(video_pixel_format_t format);
/*!
* @brief Delay the specific time.
*
* @param ms How many milli-second to delay.
*/
void VIDEO_DelayMs(uint32_t ms);
/*!
* @brief Get the pixel size in bits.
*
* @param pixelFormat The pixel format.
* @return Bits per pixel.
*/
uint8_t VIDEO_GetPixelSizeBits(video_pixel_format_t pixelFormat);
/* @} */
/*!
* @name Ring buffer.
* @{
*/
/*!
* @brief Initializes ring buffer.
*
* @param ringbuf Pointer to the ring buffer handle.
* @param buf Memory to save the items.
* @param size Size of the @p buf.
* @return Returns @ref kStatus_Success if initialize success, otherwise returns
* error code.
*/
status_t VIDEO_RINGBUF_Init(video_ringbuf_t *ringbuf, void **buf, uint32_t size);
/*!
* @brief Get one item from the ring buffer.
*
* @param ringbuf Pointer to the ring buffer handle.
* @param item Memory to save the item.
* @return Returns @ref kStatus_Success if get success, otherwise returns
* error code.
*/
status_t VIDEO_RINGBUF_Get(video_ringbuf_t *ringbuf, void **item);
/*!
* @brief Put one item to the ring buffer.
*
* @param ringbuf Pointer to the ring buffer handle.
* @param item The new item to save.
* @return Returns @ref kStatus_Success if put success, otherwise returns
* error code.
*/
status_t VIDEO_RINGBUF_Put(video_ringbuf_t *ringbuf, void *item);
/*!
* @brief Get current count of items in the ring buffer.
*
* @param ringbuf Pointer to the ring buffer handle.
* @return Returns the item count.
*/
uint32_t VIDEO_RINGBUF_GetLength(video_ringbuf_t *ringbuf);
/*!
* @brief Check whether the ring buffer is empty.
*
* @param ringbuf Pointer to the ring buffer handle.
* @return Returns true if the ring buffer is empty, otherwise returns false.
*/
bool VIDEO_RINGBUF_IsEmpty(video_ringbuf_t *ringbuf);
/*!
* @brief Check whether the ring buffer is full.
*
* @param ringbuf Pointer to the ring buffer handle.
* @return Returns true if the ring buffer is full, otherwise returns false.
*/
bool VIDEO_RINGBUF_IsFull(video_ringbuf_t *ringbuf);
/* @} */
/*!
* @name Memory Pool
*
* User can put memory block to the pool, or get memory block from the pool.
* There is no count limitation to put memory block in to the pool. The memory
* content in the pool might be modified.
*
* The memory block should be 4-byte aligned, and the dividable by 4-byte.
*
* @{
*/
/*!
* @brief Initializes memory pool.
*
* Initializes memory pool. Initial memory blocks in the memory pool is optional.
* If initial blocks are used, user should specify the initial block size and count.
*
* @param mempool Pointer to the memory pool handle.
* @param initMem Initial memory blocks to saved in the pool.
* @param size Every memory block's size (bytes) in the @p initMem.
* @param count Number of memory blocks @p initMem.
* @return Returns @ref kStatus_Success if initialize success, otherwise returns
* error code.
*/
status_t VIDEO_MEMPOOL_Init(video_mempool_t *mempool, void *initMem, uint32_t size, uint32_t count);
/*!
* @brief Create an empty memory pool.
*
* @param mempool Pointer to the memory pool handle.
*/
void VIDEO_MEMPOOL_InitEmpty(video_mempool_t *mempool);
/*!
* @brief Put memory block in the pool.
*
* @param mempool Pointer to the memory pool handle.
* @param mem Pointer to the memory block.
*/
void VIDEO_MEMPOOL_Put(video_mempool_t *mempool, void *mem);
/*!
* @brief Get memory block in the pool.
*
* @param mempool Pointer to the memory pool handle.
* @return The memory block get from pool. If the pool is empty, returns NULL.
*/
void *VIDEO_MEMPOOL_Get(video_mempool_t *mempool);
/*!
* @brief How many memory blocks in the pool.
*
* @param mempool Pointer to the memory pool handle.
* @return The memory block count in the pool
*/
uint32_t VIDEO_MEMPOOL_GetCount(video_mempool_t *mempool);
/* @} */
#if defined(__cplusplus)
}
#endif
#endif /* _FSL_VIDEO_COMMON_H_ */

View File

@ -6,6 +6,7 @@ path = [cwd + '/CMSIS/Include',cwd + '/MIMXRT1060', cwd + '/MIMXRT1060/drivers']
src = Split('''
MIMXRT1060/system_MIMXRT1062.c
MIMXRT1060/drivers/fsl_common.c
MIMXRT1060/drivers/fsl_common_arm.c
MIMXRT1060/drivers/fsl_clock.c
MIMXRT1060/drivers/fsl_cache.c
''')
@ -53,6 +54,12 @@ if GetDepend(['BSP_USING_SDRAM']):
if GetDepend(['BSP_USING_LCD']):
src += ['MIMXRT1060/drivers/fsl_elcdif.c']
if GetDepend(['DEMO_PANEL_RK043FN02H']):
src += ['MIMXRT1060/drivers/fsl_ft5406_rt.c']
if GetDepend(['DEMO_PANEL_RK043FN66HS']):
src += ['MIMXRT1060/drivers/fsl_video_common.c', 'MIMXRT1060/drivers/fsl_gt911.c']
if GetDepend(['BSP_USING_CACHE']):
src += ['MIMXRT1060/drivers/fsl_cache.c']