“0a2738ddd0a52ccddffdddd3351eeb55c79f99ea”上不存在“friends/index.html”
未验证 提交 20067853 编写于 作者: W Wayne 提交者: GitHub

[bsp/nuvoton] Upload missing files. (#6052)

* [bsp/nuvoton] Upload missing files.
Co-authored-by: NWayne Lin <wclin@nuvoton.com>
上级 c16eaf55
/**************************************************************************//**
* @file nu_trng.h
* @version V3.00
* @brief TRNG driver header file
*
* @copyright SPDX-License-Identifier: Apache-2.0
* @copyright Copyright (C) 2021 Nuvoton Technology Corp. All rights reserved.
******************************************************************************/
#ifndef __NU_TRNG_H__
#define __NU_TRNG_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup Standard_Driver Standard Driver
@{
*/
/** @addtogroup TRNG_Driver TRNG Driver
@{
*/
/** @addtogroup M460_TRNG_EXPORTED_MACROS TRNG Exported Macros
@{
*/
/*----------------------------------------------------------------------------------------------*/
/* Macros */
/*----------------------------------------------------------------------------------------------*/
/**
* @brief Let TRNG engine know the currrent PCLK frequency. The CLKPSC is the peripheral
* clock frequency range for the selected value , the CLKPSC setting must be higher
* than or equal to the actual peripheral clock frequency (for correct random generation).
* @param clkpsc 0: PCLK is 80~100 MHz
* 1: PCLK is 60~80 MHz
* 2: PCLK is 50~60 MHz
* 3: PCLK is 40~50 MHz
* 4: PCLK is 30~40 MHz
* 5: PCLK is 25~30 MHz
* 6: PCLK is 20~25 MHz
* 7: PCLK is 15~20 MHz
* 8: PCLK is 12~15 MHz
* 9: PCLK is 9~12 MHz
*
* @return None
* \hideinitializer
*/
#define TRNG_SET_CLKP(clkpsc) do { TRNG->CTL = (TRNG->CTL&~TRNG_CTL_CLKP_Msk)|((clkpsc & 0xf)<<TRNG_CTL_CLKP_Pos); } while(0);
/*@}*/ /* end of group M460_TRNG_EXPORTED_MACROS */
/** @addtogroup TRNG_EXPORTED_FUNCTIONS TRNG Exported Functions
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* Functions */
/*---------------------------------------------------------------------------------------------------------*/
int32_t TRNG_Open(void);
int32_t TRNG_GenWord(uint32_t *u32RndNum);
int32_t TRNG_GenBignum(uint8_t u8BigNum[], int32_t i32Len);
int32_t TRNG_GenBignumHex(char cBigNumHex[], int32_t i32Len);
/*@}*/ /* end of group TRNG_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group TRNG_Driver */
/*@}*/ /* end of group Standard_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __NU_TRNG_H__ */
/**************************************************************************//**
* @file trng.c
* @version V3.00
* @brief M460 series TRNG driver source file
*
* @copyright SPDX-License-Identifier: Apache-2.0
* @copyright Copyright (C) 2021 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include <stdio.h>
#include "NuMicro.h"
/** @addtogroup Standard_Driver Standard Driver
@{
*/
/** @addtogroup TRNG_Driver TRNG Driver
@{
*/
/** @addtogroup TRNG_EXPORTED_FUNCTIONS TRNG Exported Functions
@{
*/
/**
* @brief Initialize TRNG hardware.
* @return TRNG hardware enable success or failed.
* @retval 0 Success
* @retval -1 Time-out. TRNG hardware may not be enabled.
*/
int32_t TRNG_Open(void)
{
uint32_t u32TimeOutCount = SystemCoreClock; /* 1 second time-out */
SYS->IPRST1 |= SYS_IPRST1_TRNGRST_Msk;
SYS->IPRST1 ^= SYS_IPRST1_TRNGRST_Msk;
TRNG->CTL |= TRNG_CTL_TRNGEN_Msk;
TRNG->ACT |= TRNG_ACT_ACT_Msk;
/* Waiting for ready */
while ((TRNG->CTL & TRNG_CTL_READY_Msk) == 0)
{
if (--u32TimeOutCount == 0) return -1; /* Time-out error */
}
return 0;
}
/**
* @brief Generate a 32-bits random number word.
* @param[out] u32RndNum The output 32-bits word random number.
*
* @return Success or time-out.
* @retval 0 Success
* @retval -1 Time-out. TRNG hardware may not be enabled.
*/
int32_t TRNG_GenWord(uint32_t *u32RndNum)
{
uint32_t i, u32Reg, timeout;
*u32RndNum = 0;
u32Reg = TRNG->CTL;
for (i = 0; i < 4; i++)
{
TRNG->CTL = TRNG_CTL_TRNGEN_Msk | u32Reg;
/* TRNG should generate one byte per 125*8 us */
for (timeout = (CLK_GetHCLKFreq() / 100); timeout > 0; timeout--)
{
if (TRNG->CTL & TRNG_CTL_DVIF_Msk)
break;
}
if (timeout == 0)
return -1;
*u32RndNum |= ((TRNG->DATA & 0xff) << i * 8);
}
return 0;
}
/**
* @brief Generate a big number in binary format.
* @param[out] u8BigNum The output big number.
* @param[in] i32Len Request bit length of the output big number. It must be multiple of 8.
*
* @return Success or time-out.
* @retval 0 Success
* @retval -1 Time-out. TRNG hardware may not be enabled.
*/
int32_t TRNG_GenBignum(uint8_t u8BigNum[], int32_t i32Len)
{
uint32_t i, u32Reg, timeout;
u32Reg = TRNG->CTL;
for (i = 0; i < i32Len / 8; i++)
{
TRNG->CTL = TRNG_CTL_TRNGEN_Msk | u32Reg;
/* TRNG should generate one byte per 125*8 us */
for (timeout = (CLK_GetHCLKFreq() / 100); timeout > 0; timeout--)
{
if (TRNG->CTL & TRNG_CTL_DVIF_Msk)
break;
}
if (timeout == 0)
return -1;
u8BigNum[i] = (TRNG->DATA & 0xff);
}
return 0;
}
/**
* @brief Generate a big number in hex format.
* @param[out] cBigNumHex The output hex format big number.
* @param[in] i32Len Request bit length of the output big number. It must be multiple of 8.
*
* @return Success or time-out.
* @retval 0 Success
* @retval -1 Time-out. TRNG hardware may not be enabled.
*/
int32_t TRNG_GenBignumHex(char cBigNumHex[], int32_t i32Len)
{
uint32_t i, idx, u32Reg, timeout;
uint32_t data;
u32Reg = TRNG->CTL;
idx = 0;
for (i = 0; i < i32Len / 8; i++)
{
TRNG->CTL = TRNG_CTL_TRNGEN_Msk | u32Reg;
/* TRNG should generate one byte per 125*8 us */
for (timeout = (CLK_GetHCLKFreq() / 100); timeout > 0; timeout--)
{
if (TRNG->CTL & TRNG_CTL_DVIF_Msk)
break;
}
if (timeout == 0)
return -1;
data = (TRNG->DATA & 0xff);
if (data >= 0xA0)
cBigNumHex[idx++] = ((data >> 4) & 0xf) - 10 + 'A';
else
cBigNumHex[idx++] = ((data >> 4) & 0xf) + '0';
data &= 0xf;
if (data >= 0xA)
cBigNumHex[idx++] = data - 10 + 'A';
else
cBigNumHex[idx++] = data + '0';
}
cBigNumHex[idx] = 0;
return 0;
}
/*@}*/ /* end of group TRNG_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group TRNG_Driver */
/*@}*/ /* end of group Standard_Driver */
此差异已折叠。
此差异已折叠。
Import('RTT_ROOT')
from building import *
cwd = GetCurrentDir()
group = []
src = Split("""
lcd_fsa506.c
""")
CPPPATH = [cwd]
if GetDepend('NU_PKG_USING_FSA506_EBI'):
src += Glob('fsa506_ebi.c')
if GetDepend('NU_PKG_USING_FSA506'):
group = DefineGroup('nu_pkgs_fsa506', src, depend = [''], CPPPATH = CPPPATH)
Return('group')
/**************************************************************************//**
*
* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-2-23 Wayne First version
*
******************************************************************************/
#include <rtconfig.h>
#if defined(NU_PKG_USING_FSA506_EBI)
#include <lcd_fsa506.h>
#include "drv_pdma.h"
#define FSA506_ADDR_CMD 0x0
#define FSA506_ADDR_DATA 0x0
#if defined(FSA506_EBI_16BIT)
#define fsa506_reg_write(RegAddr) (*((volatile uint16_t *)(s_u32AccessBase+(FSA506_ADDR_CMD))) = (RegAddr))
#define fsa506_read_data() (*((volatile uint16_t *)(s_u32AccessBase+(FSA506_ADDR_DATA))))
#define fsa506_write_data(Data) (*((volatile uint16_t *)(s_u32AccessBase+(FSA506_ADDR_DATA))) = (Data))
#else
#define fsa506_reg_write(RegAddr) (*((volatile uint8_t *)(s_u32AccessBase+(FSA506_ADDR_CMD))) = (RegAddr))
#define fsa506_read_data() (*((volatile uint8_t *)(s_u32AccessBase+(FSA506_ADDR_DATA))))
#define fsa506_write_data(Data) (*((volatile uint8_t *)(s_u32AccessBase+(FSA506_ADDR_DATA))) = (Data))
#endif
static rt_uint32_t s_u32AccessBase = 0;
void fsa506_send_cmd(rt_uint8_t cmd)
{
CLR_RS;
fsa506_reg_write(cmd);
SET_RS;
}
void fsa506_send_cmd_parameter(rt_uint8_t data)
{
fsa506_write_data(data);
}
void fsa506_send_cmd_done(void)
{
CLR_RS;
fsa506_reg_write(0x80);
SET_RS;
}
void fsa506_write_reg(rt_uint8_t cmd, rt_uint8_t data)
{
fsa506_send_cmd(cmd);
fsa506_send_cmd_parameter(data);
fsa506_send_cmd_done();
}
void fsa506_send_pixel_data(rt_uint16_t color)
{
#if 1
// for LV_COLOR_16_SWAP
//BGR, B is high byte
fsa506_write_data(color & 0xffu);
fsa506_write_data((color >> 8) & 0xffu);
#else
//RGB, R is high byte
fsa506_write_data((color >> 8) & 0xffu);
fsa506_write_data(color & 0xffu);
#endif
}
void fsa506_send_pixels(rt_uint16_t *pixels, int len)
{
int count = len / sizeof(rt_uint16_t);
if (count < 512)
{
// CPU feed
int i = 0;
while (i < count)
{
fsa506_send_pixel_data(pixels[i]);
i++;
}
}
else
{
// PDMA-M2M feed
// Must enable LV_COLOR_16_SWAP definition in LVGL.
nu_pdma_mempush((void *)(s_u32AccessBase + (FSA506_ADDR_DATA)), (void *)pixels, 8, len);
}
}
void fsa506_set_column(uint16_t StartCol, uint16_t EndCol)
{
fsa506_write_reg(0x0, (StartCol >> 8) & 0xFF);
fsa506_write_reg(0x1, StartCol & 0xFF);
fsa506_write_reg(0x2, (EndCol >> 8) & 0xFF);
fsa506_write_reg(0x3, EndCol & 0xFF);
}
void fsa506_set_page(uint16_t StartPage, uint16_t EndPage)
{
fsa506_write_reg(0x4, (StartPage >> 8) & 0xFF);
fsa506_write_reg(0x5, StartPage & 0xFF);
fsa506_write_reg(0x6, (EndPage >> 8) & 0xFF);
fsa506_write_reg(0x7, EndPage & 0xFF);
}
void fsa506_lcd_get_pixel(char *color, int x, int y)
{
//Not supported.
return;
}
rt_err_t rt_hw_lcd_fsa506_ebi_init(rt_uint32_t fsa506_base)
{
s_u32AccessBase = fsa506_base;
return RT_EOK;
}
#endif /* if defined(NU_PKG_USING_FSA506_EBI) */
/**************************************************************************//**
*
* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-2-23 Wayne First version
*
******************************************************************************/
#include <rtconfig.h>
#if defined(NU_PKG_USING_FSA506)
#include <rtdevice.h>
#include <lcd_fsa506.h>
#if defined(NU_PKG_FSA506_WITH_OFFSCREEN_FRAMEBUFFER)
#if !defined(NU_PKG_FSA506_LINE_BUFFER_NUMBER)
#define NU_PKG_FSA506_LINE_BUFFER_NUMBER YSIZE_PHYS
#endif
#endif
#define fsa506_delay_ms(ms) rt_thread_mdelay(ms)
static void fsa506_fillscreen(rt_uint16_t color);
static struct rt_device_graphic_info g_FSA506Info =
{
.bits_per_pixel = 16,
.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB565,
.framebuffer = RT_NULL,
.width = XSIZE_PHYS,
.pitch = XSIZE_PHYS * 2,
.height = YSIZE_PHYS
};
static rt_err_t fsa506_pin_init(void)
{
rt_pin_mode(BOARD_USING_FSA506_PIN_DC, PIN_MODE_OUTPUT);
rt_pin_mode(BOARD_USING_FSA506_PIN_RESET, PIN_MODE_OUTPUT);
rt_pin_mode(BOARD_USING_FSA506_PIN_BACKLIGHT, PIN_MODE_OUTPUT);
rt_pin_mode(BOARD_USING_FSA506_PIN_DISPLAY, PIN_MODE_OUTPUT);
CLR_RS;
CLR_RST;
SET_BACKLIGHT_OFF;
SET_DISP_OFF;
return RT_EOK;
}
static rt_err_t fsa506_lcd_init(rt_device_t dev)
{
/* Hardware reset */
CLR_RST;
fsa506_delay_ms(100); // Delay 100ms
SET_RST;
fsa506_delay_ms(100); // Delay 100ms
fsa506_write_reg(0x40, 0x12); // Underspece
fsa506_write_reg(0x41, 0x05); // Underspece
fsa506_write_reg(0x42, 0x06); // Underspece
/* Set the panel X size */
fsa506_write_reg(0x08, (uint8_t)(XSIZE_PHYS >> 8)); //Set the panel X size H[1.0]
fsa506_write_reg(0x09, (uint8_t)(XSIZE_PHYS)); //Set the panel X size L[7:0]
/* Memory write start address */
fsa506_write_reg(0x0a, 0x00); //[17:16] bits of memory write start address
fsa506_write_reg(0x0b, 0x00); //[15:8] bits of memory write start address
fsa506_write_reg(0x0c, 0x00); //[7:0] bits of memory write start address
/* Clock & format */
fsa506_write_reg(0x10, 0x0D); //[0-1] : 20MHz, [2]: Parallel panel, [3]: Normal operation
fsa506_write_reg(0x11, 0x05); //[3-5]: RGB, [0-2]BGR
/* For TFT output timing adjust */
fsa506_write_reg(0x12, 0x00); //Hsync start position H-Byte
fsa506_write_reg(0x13, 0x00); //Hsync start position L-Byte
fsa506_write_reg(0x14, (uint8_t)(41 >> 8)); //Hsync pulse width H-Byte
fsa506_write_reg(0x15, (uint8_t)(41)); //Hsync pulse width L-Byte
fsa506_write_reg(0x16, (uint8_t)(43 >> 8)); //DE pulse start position H-Byte
fsa506_write_reg(0x17, (uint8_t)(43)); //DE pulse start position L-Byte
fsa506_write_reg(0x18, (uint8_t)(XSIZE_PHYS >> 8)); //DE pulse width H-Byte
fsa506_write_reg(0x19, (uint8_t)(XSIZE_PHYS)); //DE pulse width L-Byte
fsa506_write_reg(0x1a, (uint8_t)(525 >> 8)); //Hsync total clocks H-Byte
fsa506_write_reg(0x1b, (uint8_t)(525)); //Hsync total clocks H-Byte
fsa506_write_reg(0x1c, 0x00); //Vsync start position H-Byte
fsa506_write_reg(0x1d, 0x00); //Vsync start position L-Byte
fsa506_write_reg(0x1e, (uint8_t)(10 >> 8)); //Vsync pulse width H-Byte
fsa506_write_reg(0x1f, (uint8_t)(10)); //Vsync pulse width L-Byte
fsa506_write_reg(0x20, (uint8_t)(12 >> 8)); //Vertical DE pulse start position H-Byte
fsa506_write_reg(0x21, (uint8_t)(12)); //Vertical DE pulse start position L-Byte
fsa506_write_reg(0x22, (uint8_t)(YSIZE_PHYS >> 8)); //Vertical Active width H-Byte
fsa506_write_reg(0x23, (uint8_t)(YSIZE_PHYS)); //Vertical Active width H-Byte
fsa506_write_reg(0x24, (uint8_t)(286 >> 8)); //Vertical total width H-Byte
fsa506_write_reg(0x25, (uint8_t)(286)); //Vertical total width L-Byte
fsa506_write_reg(0x26, 0x00); //Memory read start address
fsa506_write_reg(0x27, 0x00); //Memory read start address
fsa506_write_reg(0x28, 0x00); //Memory read start address
fsa506_write_reg(0x29, 0x01); //[0] Load output timing related setting (H sync., V sync. and DE) to take effect
//[7:4] Reserved
//[3] Output pin X_DCON level control
//[2] Output clock inversion 0: Normal 1: Inverse
//[1:0] Image rotate
// 00: 0? 01: 90? 10: 270?11: 180?
fsa506_write_reg(0x2d, (1 << 2) | 0x08);
/* Set the Horizontal offset */
fsa506_write_reg(0x30, 0x00); //_H byte H-Offset[3:0]
fsa506_write_reg(0x31, 0x00); //_L byte H-Offset[7:0]
fsa506_write_reg(0x32, 0x00); //_H byte V-Offset[3:0]
fsa506_write_reg(0x33, 0x00); //_L byte V-Offset[7:0]
fsa506_write_reg(0x34, (uint8_t)(XSIZE_PHYS >> 8)); //H byte H-def[3:0]
fsa506_write_reg(0x35, (uint8_t)(XSIZE_PHYS)); //_L byte H-def[7:0]
fsa506_write_reg(0x36, (uint8_t)((2 * YSIZE_PHYS) >> 8)); //[3:0] MSB of image vertical physical resolution in memory
fsa506_write_reg(0x37, (uint8_t)(2 * YSIZE_PHYS)); //[7:0] LSB of image vertical physical resolution in memory
fsa506_fillscreen(0);
SET_DISP_ON;
SET_BACKLIGHT_ON;
return RT_EOK;
}
#if defined(NU_PKG_FSA506_WITH_OFFSCREEN_FRAMEBUFFER)
static void fsa506_fillrect(uint16_t *pixels, struct rt_device_rect_info *pRectInfo)
{
fsa506_set_column(pRectInfo->x, pRectInfo->x + pRectInfo->width - 1);
fsa506_set_page(pRectInfo->y, pRectInfo->y + pRectInfo->height - 1);
fsa506_send_cmd(0xC1);
fsa506_send_pixels(pixels, pRectInfo->height * pRectInfo->width * 2);
fsa506_send_cmd_done();
}
#endif
static void fsa506_fillscreen(rt_uint16_t color)
{
#if defined(NU_PKG_FSA506_WITH_OFFSCREEN_FRAMEBUFFER)
struct rt_device_rect_info rectinfo;
int filled_line_num = 0;
while (filled_line_num < YSIZE_PHYS)
{
int pixel_count;
rectinfo.x = 0;
rectinfo.y = filled_line_num;
rectinfo.width = XSIZE_PHYS;
rectinfo.height = (NU_PKG_FSA506_LINE_BUFFER_NUMBER < YSIZE_PHYS) ? NU_PKG_FSA506_LINE_BUFFER_NUMBER : YSIZE_PHYS;
pixel_count = XSIZE_PHYS * NU_PKG_FSA506_LINE_BUFFER_NUMBER;
rt_uint16_t *pu16ShadowBuf = (rt_uint16_t *)g_FSA506Info.framebuffer;
while (pixel_count > 0)
{
*pu16ShadowBuf++ = color;
pixel_count--;
}
fsa506_fillrect((uint16_t *)g_FSA506Info.framebuffer, &rectinfo);
filled_line_num += NU_PKG_FSA506_LINE_BUFFER_NUMBER;
}
#else
fsa506_set_column(0, (XSIZE_PHYS - 1));
fsa506_set_page(0, (YSIZE_PHYS - 1));
fsa506_send_cmd(0xC1);
for (int i = 0; i < (XSIZE_PHYS * YSIZE_PHYS); i++)
fsa506_send_pixel_data(color);
fsa506_send_cmd_done();
#endif
}
static void fsa506_lcd_set_pixel(const char *color, int x, int y)
{
fsa506_set_column(x, x);
fsa506_set_page(y, y);
fsa506_send_cmd(0xC1);
fsa506_send_pixel_data(*(uint16_t *)color);
fsa506_send_cmd_done();
}
static void fsa506_lcd_draw_hline(const char *pixel, int x1, int x2, int y)
{
fsa506_set_column(x1, x2);
fsa506_set_page(y, y);
fsa506_send_cmd(0xC1);
for (; x1 < x2; x1++)
fsa506_send_pixel_data(*(uint16_t *)pixel);
fsa506_send_cmd_done();
}
static void fsa506_lcd_draw_vline(const char *pixel, int x, int y1, int y2)
{
fsa506_set_column(x, x);
fsa506_set_page(y1, y2);
fsa506_send_cmd(0xC1);
for (; y1 < y2; y1++)
fsa506_send_pixel_data(*(uint16_t *)pixel);
fsa506_send_cmd_done();
}
static void fsa506_lcd_blit_line(const char *pixels, int x, int y, rt_size_t size)
{
rt_uint16_t *ptr = (rt_uint16_t *)pixels;
fsa506_set_column(x, x + size);
fsa506_set_page(y, y);
fsa506_send_cmd(0xC1);
while (size--)
fsa506_send_pixel_data(*ptr++);
fsa506_send_cmd_done();
}
static rt_err_t fsa506_lcd_open(rt_device_t dev, rt_uint16_t oflag)
{
return RT_EOK;
}
static rt_err_t fsa506_lcd_close(rt_device_t dev)
{
return RT_EOK;
}
static rt_err_t fsa506_lcd_control(rt_device_t dev, int cmd, void *args)
{
switch (cmd)
{
case RTGRAPHIC_CTRL_GET_INFO:
{
struct rt_device_graphic_info *info;
info = (struct rt_device_graphic_info *) args;
RT_ASSERT(info != RT_NULL);
rt_memcpy(args, (void *)&g_FSA506Info, sizeof(struct rt_device_graphic_info));
}
break;
case RTGRAPHIC_CTRL_RECT_UPDATE:
{
#if defined(NU_PKG_FSA506_WITH_OFFSCREEN_FRAMEBUFFER)
struct rt_device_rect_info *psRectInfo = (struct rt_device_rect_info *)args;
rt_uint16_t *pixels = (rt_uint16_t *)g_FSA506Info.framebuffer;
RT_ASSERT(args);
fsa506_fillrect(pixels, psRectInfo);
#else
/* nothong to be done */
#endif
}
break;
default:
break;
}
return RT_EOK;
}
static struct rt_device lcd_device;
static struct rt_device_graphic_ops fsa506_ops =
{
fsa506_lcd_set_pixel,
fsa506_lcd_get_pixel,
fsa506_lcd_draw_hline,
fsa506_lcd_draw_vline,
fsa506_lcd_blit_line
};
int rt_hw_lcd_fsa506_init(void)
{
fsa506_pin_init();
/* register lcd device */
lcd_device.type = RT_Device_Class_Graphic;
lcd_device.init = fsa506_lcd_init;
lcd_device.open = fsa506_lcd_open;
lcd_device.close = fsa506_lcd_close;
lcd_device.control = fsa506_lcd_control;
lcd_device.read = RT_NULL;
lcd_device.write = RT_NULL;
lcd_device.user_data = &fsa506_ops;
#if defined(NU_PKG_FSA506_WITH_OFFSCREEN_FRAMEBUFFER)
g_FSA506Info.framebuffer = rt_malloc_align((g_FSA506Info.pitch * NU_PKG_FSA506_LINE_BUFFER_NUMBER) + 32, 32);
RT_ASSERT(g_FSA506Info.framebuffer != RT_NULL);
g_FSA506Info.smem_len = g_FSA506Info.pitch * NU_PKG_FSA506_LINE_BUFFER_NUMBER;
#endif
/* register graphic device driver */
rt_device_register(&lcd_device, "lcd", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
return 0;
}
#ifdef RT_USING_FINSH
#define LINE_LEN 32
static void lcd_test(int argc, char *argv[])
{
uint16_t pixels[LINE_LEN];
uint16_t color;
int x, y, i;
x = y = 100;
fsa506_lcd_init(NULL);
color = 0x0; //Black, RGB
rt_kprintf("Brush 0x%X on screen.\n", color);
fsa506_fillscreen(color);
fsa506_lcd_get_pixel((char *)&color, x, y);
rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
color = 0xffff; //White, RGB
rt_kprintf("Brush 0x%X on screen.\n", color);
fsa506_fillscreen(color);
fsa506_lcd_get_pixel((char *)&color, x, y);
rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
color = 0x1f; //Blue, RGB
rt_kprintf("Brush 0x%X on screen.\n", color);
fsa506_fillscreen(color);
fsa506_lcd_get_pixel((char *)&color, x, y);
rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
color = 0x07e0; //Green, RGB
rt_kprintf("Brush 0x%X on screen.\n", color);
fsa506_fillscreen(color);
fsa506_lcd_get_pixel((char *)&color, x, y);
rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
color = 0xf800; //Red, RGB
rt_kprintf("Brush 0x%X on screen.\n", color);
fsa506_fillscreen(color);
fsa506_lcd_get_pixel((char *)&color, x, y);
rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
color = 0xffff; //White, RGB
rt_kprintf("lcd draw hline, pixel: 0x%X, x1: %d, x2: %d, y: %d\n", color, x, x + 20, y);
fsa506_lcd_draw_hline((const char *)&color, x, x + 20, y);
color = 0xffff; //White, RGB
rt_kprintf("lcd draw vline, pixel: 0x%X, x: %d, y: %d\n", color, y, y + 20);
fsa506_lcd_draw_vline((const char *)&color, x, y, y + 20);
for (i = 0; i < LINE_LEN; i++)
pixels[i] = 20 + i * 5;
x = y = 50;
rt_kprintf("lcd blit line, start: x: %d, y: %d\n", x, y);
fsa506_lcd_blit_line((const char *)&pixels[0], x, y, LINE_LEN);
x = y = 200;
color = 0x07E0; //Green, RGB
rt_kprintf("lcd set pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
fsa506_lcd_set_pixel((const char *)&color, x, y);
color = 0x0;
fsa506_lcd_get_pixel((char *)&color, x, y);
rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
x = y = 200;
color = 0x1f; //Blue, RGB
rt_kprintf("lcd set pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
fsa506_lcd_set_pixel((const char *)&color, x, y);
color = 0x0;
fsa506_lcd_get_pixel((char *)&color, x, y);
rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
x = y = 200;
color = 0xf800; //Red, RGB
rt_kprintf("lcd set pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
fsa506_lcd_set_pixel((const char *)&color, x, y);
color = 0x0;
fsa506_lcd_get_pixel((char *)&color, x, y);
rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
}
MSH_CMD_EXPORT(lcd_test, test lcd display);
#endif
#endif /* if defined(NU_PKG_USING_FSA506) */
/**************************************************************************//**
*
* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-2-23 Wayne First version
*
******************************************************************************/
#ifndef __LCD_FSA506_H__
#define __LCD_FSA506_H__
#include <rtthread.h>
#include <rtdevice.h>
#define SET_RS rt_pin_write(BOARD_USING_FSA506_PIN_DC, 1)
#define CLR_RS rt_pin_write(BOARD_USING_FSA506_PIN_DC, 0)
#define SET_RST rt_pin_write(BOARD_USING_FSA506_PIN_RESET, 1)
#define CLR_RST rt_pin_write(BOARD_USING_FSA506_PIN_RESET, 0)
#define SET_BACKLIGHT_ON rt_pin_write(BOARD_USING_FSA506_PIN_BACKLIGHT, 1)
#define SET_BACKLIGHT_OFF rt_pin_write(BOARD_USING_FSA506_PIN_BACKLIGHT, 0)
#define SET_DISP_ON rt_pin_write(BOARD_USING_FSA506_PIN_DISPLAY, 1)
#define SET_DISP_OFF rt_pin_write(BOARD_USING_FSA506_PIN_DISPLAY, 0)
//
// Physical display size
//
//#if defined(NU_PKG_FSA506_HORIZONTAL)
#define XSIZE_PHYS 480
#define YSIZE_PHYS 272
//#else
// #define XSIZE_PHYS 272
// #define YSIZE_PHYS 480
//#endif
int rt_hw_lcd_fsa506_init(void);
void fsa506_send_cmd(rt_uint8_t cmd);
void fsa506_send_cmd_parameter(rt_uint8_t data);
void fsa506_send_cmd_done(void);
void fsa506_write_reg(rt_uint8_t cmd, rt_uint8_t data);
void fsa506_set_column(rt_uint16_t StartCol, rt_uint16_t EndCol);
void fsa506_set_page(rt_uint16_t StartPage, rt_uint16_t EndPage);
void fsa506_send_pixel_data(rt_uint16_t color);
void fsa506_lcd_get_pixel(char *color, int x, int y);
void fsa506_send_pixels(rt_uint16_t *pixels, int len);
#if defined(NU_PKG_USING_FSA506_EBI)
rt_err_t rt_hw_lcd_fsa506_ebi_init(rt_uint32_t ebi_base);
#endif
#endif /* __LCD_FSA506_H__ */
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-04-11 Wayne First version
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <string.h>
#define DBG_TAG "ft5446"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#include "ft5446.h"
static struct rt_i2c_client ft5446_client;
static void ft5446_touch_up(void *buf, rt_int8_t id);
static rt_err_t ft5446_write_reg(struct rt_i2c_client *dev, rt_uint8_t reg, rt_uint8_t value)
{
struct rt_i2c_msg msgs;
rt_uint8_t buf[2];
buf[0] = reg;
buf[1] = value;
msgs.addr = dev->client_addr;
msgs.flags = RT_I2C_WR;
msgs.buf = buf;
msgs.len = sizeof(buf);
if (rt_i2c_transfer(dev->bus, &msgs, 1) == 1)
{
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}
static rt_err_t ft5446_read_reg(struct rt_i2c_client *dev, rt_uint8_t reg, rt_uint8_t *data, rt_uint8_t len)
{
struct rt_i2c_msg msgs[2];
msgs[0].addr = dev->client_addr;
msgs[0].flags = RT_I2C_WR;
msgs[0].buf = &reg;
msgs[0].len = FT_REGITER_LEN;
msgs[1].addr = dev->client_addr;
msgs[1].flags = RT_I2C_RD;
msgs[1].buf = data;
msgs[1].len = len;
if (rt_i2c_transfer(dev->bus, msgs, 2) == 2)
{
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}
static rt_int16_t pre_x[FT_MAX_TOUCH];
static rt_int16_t pre_y[FT_MAX_TOUCH];
static rt_int16_t pre_w[FT_MAX_TOUCH];
static rt_uint8_t s_tp_dowm[FT_MAX_TOUCH];
static void ft5446_touch_up(void *buf, rt_int8_t id)
{
struct rt_touch_data *read_data = (struct rt_touch_data *)buf;
if (s_tp_dowm[id] == 1)
{
s_tp_dowm[id] = 0;
read_data[id].event = RT_TOUCH_EVENT_UP;
}
else
{
read_data[id].event = RT_TOUCH_EVENT_NONE;
}
read_data[id].timestamp = rt_touch_get_ts();
read_data[id].width = pre_w[id];
read_data[id].x_coordinate = pre_x[id];
read_data[id].y_coordinate = pre_y[id];
read_data[id].track_id = id;
pre_x[id] = -1; /* last point is none */
pre_y[id] = -1;
pre_w[id] = -1;
//LOG_I("%s (%d)\n", __func__, id);
}
static void ft5446_touch_down(void *buf, rt_int8_t id, rt_int16_t x, rt_int16_t y, rt_int16_t w)
{
struct rt_touch_data *read_data = (struct rt_touch_data *)buf;
if (s_tp_dowm[id] == 1)
{
read_data[id].event = RT_TOUCH_EVENT_MOVE;
}
else
{
read_data[id].event = RT_TOUCH_EVENT_DOWN;
s_tp_dowm[id] = 1;
}
read_data[id].timestamp = rt_touch_get_ts();
read_data[id].width = w;
read_data[id].x_coordinate = x;
read_data[id].y_coordinate = y;
read_data[id].track_id = id;
pre_x[id] = x; /* save last point */
pre_y[id] = y;
pre_w[id] = w;
//LOG_I("%s (%d %d %d %d)\n", __func__, id, x, y, w );
}
static int8_t pre_id[FT_MAX_TOUCH];
static S_FT_REGMAP sFtRegMap;
static rt_uint8_t pre_touch = 0;
static rt_size_t ft5446_read_point(struct rt_touch_device *touch, void *buf, rt_size_t read_num)
{
int i;
rt_err_t error = 0;
rt_int32_t touch_event, touchid;
RT_ASSERT(touch);
RT_ASSERT(buf);
RT_ASSERT(read_num != 0);
RT_ASSERT(read_num <= FT_MAX_TOUCH);
error = ft5446_read_reg(&ft5446_client, 0, (rt_uint8_t *)&sFtRegMap, sizeof(sFtRegMap));
if (error)
{
LOG_E("get touch data failed, err:%d\n", error);
goto exit_read_point;
}
if (sFtRegMap.u8TDStatus > FT_MAX_TOUCH)
{
LOG_E("FW report max point:%d > panel info. max:%d\n", sFtRegMap.u8TDStatus, FT_MAX_TOUCH);
goto exit_read_point;
}
if (pre_touch > sFtRegMap.u8TDStatus) /* point up */
{
for (i = 0; i < FT_MAX_TOUCH; i++)
{
rt_uint8_t j;
for (j = 0; j < sFtRegMap.u8TDStatus; j++) /* this time touch num */
{
touchid = sFtRegMap.m_sTP[j].u8TouchID;
if (touchid >= 0x0f)
continue;
if (pre_id[i] == touchid) /* this id is not free */
break;
}
if ((j == sFtRegMap.u8TDStatus) && (pre_id[i] != -1)) /* free this node */
{
// LOG_I("free %d tid=%d\n", i, pre_id[i]);
ft5446_touch_up(buf, pre_id[i]);
pre_id[i] = -1;
}
}
}
for (i = 0; i < sFtRegMap.u8TDStatus; i++)
{
touch_event = sFtRegMap.m_sTP[i].u8EvtFlag;
touchid = sFtRegMap.m_sTP[i].u8TouchID;
//LOG_I("(%d/%d) %d %d\n", i, sFtRegMap.u8TDStatus, touchid, touch_event );
if (touchid >= 0x0f)
continue;
pre_id[i] = touchid;
if ((touch_event == FT_EVENTFLAG_PRESS_DOWN) || (touch_event == FT_EVENTFLAG_CONTACT))
{
rt_uint16_t x, y, w;
x = ((uint16_t)sFtRegMap.m_sTP[i].u8X_11_8 << 8) | sFtRegMap.m_sTP[i].u8X_7_0;
y = ((uint16_t)sFtRegMap.m_sTP[i].u8Y_11_8 << 8) | sFtRegMap.m_sTP[i].u8Y_7_0;
w = sFtRegMap.m_sTP[i].m_u8Weight;
//LOG_I("[%d] (%d %d %d %d)\n", touch_event, touchid, x, y, w );
if (x >= touch->info.range_x || y >= touch->info.range_y)
{
LOG_E("invalid position, X[%d,%u,%d], Y[%d,%u,%d]\n",
0, x, touch->info.range_x,
0, y, touch->info.range_y);
continue;
}
ft5446_touch_down(buf, touchid, x, y, w);
}
else
{
// Up
ft5446_touch_up(buf, touchid);
}
} // for (i = 0; i < sFtRegMap.u8TDStatus; i++)
pre_touch = sFtRegMap.u8TDStatus;
return read_num;
exit_read_point:
pre_touch = 0;
return 0;
}
static rt_err_t ft5446_control(struct rt_touch_device *touch, int cmd, void *arg)
{
switch (cmd)
{
case RT_TOUCH_CTRL_GET_INFO:
{
struct rt_touch_info *info = (struct rt_touch_info *)arg;
RT_ASSERT(arg);
rt_memcpy(info, &touch->info, sizeof(struct rt_touch_info));
break;
}
case RT_TOUCH_CTRL_GET_ID:
break;
case RT_TOUCH_CTRL_SET_X_RANGE:
break;
case RT_TOUCH_CTRL_SET_Y_RANGE:
break;
case RT_TOUCH_CTRL_SET_X_TO_Y:
break;
case RT_TOUCH_CTRL_SET_MODE:
break;
default:
break;
}
return RT_EOK;
}
static struct rt_touch_ops ft5446_touch_ops =
{
.touch_readpoint = ft5446_read_point,
.touch_control = ft5446_control,
};
static void ft5446_init(struct rt_i2c_client *dev)
{
ft5446_write_reg(dev, 0x0, 0);
}
int rt_hw_ft5446_init(const char *name, struct rt_touch_config *cfg)
{
struct rt_touch_device *touch_device = RT_NULL;
rt_uint32_t bus_speed = 400000;
touch_device = (struct rt_touch_device *)rt_malloc(sizeof(struct rt_touch_device));
if (touch_device == RT_NULL)
{
LOG_E("touch device malloc fail");
return -RT_ERROR;
}
rt_memset((void *)touch_device, 0, sizeof(struct rt_touch_device));
/* hw init*/
rt_pin_mode(*(rt_uint8_t *)cfg->user_data, PIN_MODE_OUTPUT);
rt_pin_write(*(rt_uint8_t *)cfg->user_data, PIN_LOW);
rt_thread_delay(5);
rt_pin_write(*(rt_uint8_t *)cfg->user_data, PIN_HIGH);
rt_thread_delay(200);
rt_pin_mode(cfg->irq_pin.pin, cfg->irq_pin.mode);
ft5446_client.bus = (struct rt_i2c_bus_device *)rt_device_find(cfg->dev_name);
if (ft5446_client.bus == RT_NULL)
{
LOG_E("Can't find %s device", cfg->dev_name);
return -RT_ERROR;
}
if (rt_device_open((rt_device_t)ft5446_client.bus, RT_DEVICE_FLAG_RDWR) != RT_EOK)
{
LOG_E("open %s device failed", cfg->dev_name);
return -RT_ERROR;
}
if (rt_device_control((rt_device_t)ft5446_client.bus, RT_I2C_DEV_CTRL_CLK, &bus_speed) != RT_EOK)
{
LOG_E("control %s device failed", cfg->dev_name);
return -RT_ERROR;
}
ft5446_client.client_addr = FT5446_ADDRESS;
ft5446_init(&ft5446_client);
rt_memset(&pre_x[0], 0xff, FT_MAX_TOUCH * sizeof(int16_t));
rt_memset(&pre_y[0], 0xff, FT_MAX_TOUCH * sizeof(int16_t));
rt_memset(&pre_w[0], 0xff, FT_MAX_TOUCH * sizeof(int16_t));
rt_memset(&s_tp_dowm[0], 0, FT_MAX_TOUCH * sizeof(int16_t));
rt_memset(&pre_id[0], 0xff, FT_MAX_TOUCH * sizeof(int8_t));
/* register touch device */
touch_device->info.type = RT_TOUCH_TYPE_CAPACITANCE;
touch_device->info.vendor = RT_TOUCH_VENDOR_FT;
touch_device->info.range_x = BSP_LCD_WIDTH;
touch_device->info.range_y = BSP_LCD_HEIGHT;
touch_device->info.point_num = FT_MAX_TOUCH;
rt_memcpy(&touch_device->config, cfg, sizeof(struct rt_touch_config));
touch_device->ops = &ft5446_touch_ops;
rt_hw_touch_register(touch_device, name, RT_DEVICE_FLAG_INT_RX, RT_NULL);
LOG_I("touch device ft5446 init success");
return RT_EOK;
}
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-04-11 Wayne the first version
*/
#ifndef __FT5446_H__
#define __FT5446_H__
#include "touch.h"
#define FT_REGITER_LEN 1
#define FT_MAX_TOUCH 5
#define FT5446_ADDRESS 0x38
#pragma anon_unions
typedef struct
{
//03H
union
{
uint8_t m_u8XH;
struct
{
uint8_t u8X_11_8: 4;
uint8_t : 2;
uint8_t u8EvtFlag: 2;
#define FT_EVENTFLAG_PRESS_DOWN 0x0
#define FT_EVENTFLAG_LIFT_UP 0x1
#define FT_EVENTFLAG_CONTACT 0x2
#define FT_EVENTFLAG_NONE 0x3
};
};
//04H
union
{
uint8_t m_u8XL;
struct
{
uint8_t u8X_7_0;
};
};
//05H
union
{
uint8_t m_u8YH;
struct
{
uint8_t u8Y_11_8: 4;
uint8_t u8TouchID: 4; /* Touch ID of Touch Point, this value is 0x0F when the ID is invalid */
};
};
//06H
union
{
uint8_t m_u8YL;
struct
{
uint8_t u8Y_7_0;
};
};
//07H
uint8_t m_u8Weight; /* Touch pressure value */
//08H
union
{
uint8_t m_u8Misc;
struct
{
uint8_t : 4;
uint8_t u8TouchArea: 4; /* Touch area value */
};
};
} S_FT_TP;
#pragma pack(push)
#pragma pack(4)
typedef struct
{
union
{
uint8_t m_u8ModeSwitch;
#define FT_DEVICE_MODE_WORKING 0x0
#define FT_DEVICE_MODE_TEST 0x4
struct
{
uint8_t : 4;
uint8_t u8DevMode: 3;
uint8_t : 1;
};
};
uint8_t m_u8Guesture;
#define FT_GESTURE_ID_MOVE_UP 0x10
#define FT_GESTURE_ID_MOVE_RIGHT 0x14
#define FT_GESTURE_ID_MOVE_DOWN 0x18
#define FT_GESTURE_ID_MOVE_LEFT 0x1C
#define FT_GESTURE_ID_MOVE_IN 0x48
#define FT_GESTURE_ID_MOVE_OUT 0x49
#define FT_GESTURE_ID_MOVE_NONE 0x00
union
{
uint8_t m_u8Status;
struct
{
uint8_t u8TDStatus: 4;
uint8_t : 4;
};
};
S_FT_TP m_sTP[FT_MAX_TOUCH];
} S_FT_REGMAP;
#pragma pack(pop)
int rt_hw_ft5446_init(const char *name, struct rt_touch_config *cfg);
#endif /* __FT5446_H__ */
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-04-11 Wayne First version
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <string.h>
#define DBG_TAG "st1663i"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#include "st1663i.h"
static struct rt_i2c_client st1663i_client;
static void st1663i_touch_up(void *buf, rt_int8_t id);
static rt_err_t st1663i_write_reg(struct rt_i2c_client *dev, rt_uint8_t reg, rt_uint8_t value)
{
struct rt_i2c_msg msgs;
rt_uint8_t buf[2];
buf[0] = reg;
buf[1] = value;
msgs.addr = dev->client_addr;
msgs.flags = RT_I2C_WR;
msgs.buf = buf;
msgs.len = sizeof(buf);
if (rt_i2c_transfer(dev->bus, &msgs, 1) == 1)
{
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}
static rt_err_t st1663i_read_reg(struct rt_i2c_client *dev, rt_uint8_t reg, rt_uint8_t *data, rt_uint8_t len)
{
struct rt_i2c_msg msgs[2];
msgs[0].addr = dev->client_addr;
msgs[0].flags = RT_I2C_WR;
msgs[0].buf = &reg;
msgs[0].len = ST_REGITER_LEN;
msgs[1].addr = dev->client_addr;
msgs[1].flags = RT_I2C_RD;
msgs[1].buf = data;
msgs[1].len = len;
if (rt_i2c_transfer(dev->bus, msgs, 2) == 2)
{
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}
static rt_int16_t pre_x[ST_MAX_TOUCH];
static rt_int16_t pre_y[ST_MAX_TOUCH];
static rt_int16_t pre_w[ST_MAX_TOUCH];
static rt_uint8_t s_tp_dowm[ST_MAX_TOUCH];
static void st1663i_touch_up(void *buf, rt_int8_t id)
{
struct rt_touch_data *read_data = (struct rt_touch_data *)buf;
if (s_tp_dowm[id] == 1)
{
s_tp_dowm[id] = 0;
read_data[id].event = RT_TOUCH_EVENT_UP;
}
else
{
read_data[id].event = RT_TOUCH_EVENT_NONE;
}
read_data[id].timestamp = rt_touch_get_ts();
read_data[id].width = pre_w[id];
read_data[id].x_coordinate = pre_x[id];
read_data[id].y_coordinate = pre_y[id];
read_data[id].track_id = id;
pre_x[id] = -1; /* last point is none */
pre_y[id] = -1;
pre_w[id] = -1;
//LOG_I("%s (%d)\n", __func__, id);
}
static void st1663i_touch_down(void *buf, rt_int8_t id, rt_int16_t x, rt_int16_t y, rt_int16_t w)
{
struct rt_touch_data *read_data = (struct rt_touch_data *)buf;
if (s_tp_dowm[id] == 1)
{
read_data[id].event = RT_TOUCH_EVENT_MOVE;
}
else
{
read_data[id].event = RT_TOUCH_EVENT_DOWN;
s_tp_dowm[id] = 1;
}
read_data[id].timestamp = rt_touch_get_ts();
read_data[id].width = w;
read_data[id].x_coordinate = x;
read_data[id].y_coordinate = y;
read_data[id].track_id = id;
pre_x[id] = x; /* save last point */
pre_y[id] = y;
pre_w[id] = w;
//LOG_I("%s (%d %d %d %d)\n", __func__, id, x, y, w );
}
static int8_t pre_id[ST_MAX_TOUCH];
static S_ST_REGMAP sStRegMap;
static rt_uint8_t pre_touch = 0;
static rt_size_t st1663i_read_point(struct rt_touch_device *touch, void *buf, rt_size_t read_num)
{
int i;
rt_err_t error = 0;
rt_int32_t touch_event, touchid;
RT_ASSERT(touch);
RT_ASSERT(buf);
RT_ASSERT(read_num != 0);
RT_ASSERT(read_num <= ST_MAX_TOUCH);
error = st1663i_read_reg(&st1663i_client, 0x10, (rt_uint8_t *)&sStRegMap, sizeof(sStRegMap));
if (error)
{
LOG_E("get touch data failed, err:%d\n", error);
goto exit_read_point;
}
if (sStRegMap.u8Fingers > ST_MAX_TOUCH)
{
LOG_E("FW report max point:%d > panel info. max:%d\n", sStRegMap.u8Fingers, ST_MAX_TOUCH);
goto exit_read_point;
}
if (pre_touch > sStRegMap.u8Fingers) /* point up */
{
for (i = 0; i < ST_MAX_TOUCH; i++)
{
rt_uint8_t j;
for (j = 0; j < sStRegMap.u8Fingers; j++) /* this time touch num */
{
touchid = i;
if (pre_id[i] == touchid) /* this id is not free */
break;
}
if ((j == sStRegMap.u8Fingers) && (pre_id[i] != -1)) /* free this node */
{
// LOG_I("free %d tid=%d\n", i, pre_id[i]);
st1663i_touch_up(buf, pre_id[i]);
pre_id[i] = -1;
}
}
}
for (i = 0; i < sStRegMap.u8Fingers; i++)
{
touch_event = sStRegMap.m_sTP[i].u8Valid;
touchid = i;
//LOG_I("(%d/%d) %d %d\n", i, sStRegMap.u8Fingers, touchid, touch_event);
pre_id[i] = touchid;
if (touch_event)
{
rt_uint16_t x, y, w;
x = ((uint16_t)sStRegMap.m_sTP[i].u8X0_H << 8) | sStRegMap.m_sTP[i].m_u8X0_L;
y = ((uint16_t)sStRegMap.m_sTP[i].u8Y0_H << 8) | sStRegMap.m_sTP[i].m_u8Y0_L;
w = sStRegMap.m_sTP[i].m_u8Z;
//LOG_I("[%d] (%d %d %d %d)\n", touch_event, touchid, x, y, w);
if (x >= touch->info.range_x || y >= touch->info.range_y)
{
LOG_E("invalid position, X[%d,%u,%d], Y[%d,%u,%d]\n",
0, x, touch->info.range_x,
0, y, touch->info.range_y);
continue;
}
st1663i_touch_down(buf, touchid, x, y, w);
}
else
{
// Up
st1663i_touch_up(buf, touchid);
}
} // for (i = 0; i < sStRegMap.u8TDStatus; i++)
pre_touch = sStRegMap.u8Fingers;
return read_num;
exit_read_point:
pre_touch = 0;
return 0;
}
static rt_err_t st1663i_control(struct rt_touch_device *touch, int cmd, void *arg)
{
switch (cmd)
{
case RT_TOUCH_CTRL_GET_INFO:
{
struct rt_touch_info *info = (struct rt_touch_info *)arg;
RT_ASSERT(arg);
rt_memcpy(info, &touch->info, sizeof(struct rt_touch_info));
break;
}
case RT_TOUCH_CTRL_GET_ID:
break;
case RT_TOUCH_CTRL_SET_X_RANGE:
break;
case RT_TOUCH_CTRL_SET_Y_RANGE:
break;
case RT_TOUCH_CTRL_SET_X_TO_Y:
break;
case RT_TOUCH_CTRL_SET_MODE:
break;
default:
break;
}
return RT_EOK;
}
static struct rt_touch_ops st1663i_touch_ops =
{
.touch_readpoint = st1663i_read_point,
.touch_control = st1663i_control,
};
static void st1663i_init(struct rt_i2c_client *dev)
{
st1663i_write_reg(dev, 0x0, 0);
}
int rt_hw_st1663i_init(const char *name, struct rt_touch_config *cfg)
{
struct rt_touch_device *touch_device = RT_NULL;
rt_uint32_t bus_speed = 400000;
touch_device = (struct rt_touch_device *)rt_malloc(sizeof(struct rt_touch_device));
if (touch_device == RT_NULL)
{
LOG_E("touch device malloc fail");
return -RT_ERROR;
}
rt_memset((void *)touch_device, 0, sizeof(struct rt_touch_device));
/* hw init*/
rt_pin_mode(*(rt_uint8_t *)cfg->user_data, PIN_MODE_OUTPUT);
rt_pin_write(*(rt_uint8_t *)cfg->user_data, PIN_LOW);
rt_thread_delay(5);
rt_pin_write(*(rt_uint8_t *)cfg->user_data, PIN_HIGH);
rt_thread_delay(200);
rt_pin_mode(cfg->irq_pin.pin, cfg->irq_pin.mode);
st1663i_client.bus = (struct rt_i2c_bus_device *)rt_device_find(cfg->dev_name);
if (st1663i_client.bus == RT_NULL)
{
LOG_E("Can't find %s device", cfg->dev_name);
return -RT_ERROR;
}
if (rt_device_open((rt_device_t)st1663i_client.bus, RT_DEVICE_FLAG_RDWR) != RT_EOK)
{
LOG_E("open %s device failed", cfg->dev_name);
return -RT_ERROR;
}
if (rt_device_control((rt_device_t)st1663i_client.bus, RT_I2C_DEV_CTRL_CLK, &bus_speed) != RT_EOK)
{
LOG_E("control %s device failed", cfg->dev_name);
return -RT_ERROR;
}
st1663i_client.client_addr = ST1663I_ADDRESS;
st1663i_init(&st1663i_client);
rt_memset(&pre_x[0], 0xff, ST_MAX_TOUCH * sizeof(int16_t));
rt_memset(&pre_y[0], 0xff, ST_MAX_TOUCH * sizeof(int16_t));
rt_memset(&pre_w[0], 0xff, ST_MAX_TOUCH * sizeof(int16_t));
rt_memset(&s_tp_dowm[0], 0, ST_MAX_TOUCH * sizeof(int16_t));
rt_memset(&pre_id[0], 0xff, ST_MAX_TOUCH * sizeof(int8_t));
/* register touch device */
touch_device->info.type = RT_TOUCH_TYPE_CAPACITANCE;
touch_device->info.vendor = RT_TOUCH_VENDOR_UNKNOWN;
touch_device->info.range_x = BSP_LCD_WIDTH;
touch_device->info.range_y = BSP_LCD_HEIGHT;
touch_device->info.point_num = ST_MAX_TOUCH;
rt_memcpy(&touch_device->config, cfg, sizeof(struct rt_touch_config));
touch_device->ops = &st1663i_touch_ops;
rt_hw_touch_register(touch_device, name, RT_DEVICE_FLAG_INT_RX, RT_NULL);
LOG_I("touch device st1663i init success");
return RT_EOK;
}
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-04-11 Wayne the first version
*/
#ifndef __ST1663I_H__
#define __ST1663I_H__
#include "touch.h"
#define ST_REGITER_LEN 1
#define ST_MAX_TOUCH 5
#define ST1663I_ADDRESS 0x55
#pragma anon_unions
typedef struct
{
//012H*n+0 (n=0, 1, ...,4)
union
{
uint8_t m_u8XY0_H;
struct
{
uint8_t u8Y0_H: 3;
uint8_t : 1;
uint8_t u8X0_H: 3;
uint8_t u8Valid: 1;
};
};
//012H*n+1 (n=0, 1, ...,4)
uint8_t m_u8X0_L;
//012H*n+2 (n=0, 1, ...,4)
uint8_t m_u8Y0_L;
//012H*n+3 (n=0, 1, ...,4)
uint8_t m_u8Z;
} S_ST_TP;
#pragma pack(push)
#pragma pack(4)
typedef struct
{
union
{
uint8_t m_u8TouchInfo;
struct
{
uint8_t u8Fingers: 4;
uint8_t : 4;
};
};
uint8_t m_u8Keys;
S_ST_TP m_sTP[ST_MAX_TOUCH];
} S_ST_REGMAP;
#pragma pack(pop)
int rt_hw_st1663i_init(const char *name, struct rt_touch_config *cfg);
#endif /* __ST1663I_H__ */
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-12-17 Wayne The first version
*/
/**
* @file lv_gpu_n9h30_ge2d.c
*
*/
/*********************
* INCLUDES
*********************/
#include <lvgl.h>
#if LV_USE_GPU_N9H30_GE2D && LV_VERSION_CHECK(8, 2, 0)
#include "lv_gpu_n9h30_ge2d.h"
#include "nu_2d.h"
#include "mmu.h"
/*********************
* DEFINES
*********************/
#if LV_COLOR_16_SWAP
#error "Can't use GE2D with LV_COLOR_16_SWAP 1"
#endif
#if !((LV_COLOR_DEPTH == 16) || (LV_COLOR_DEPTH == 32))
/*Can't use GPU with other formats*/
#error "Can't use GPU with other formats"
#endif
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void lv_draw_n9h30_ge2d_blend_fill(lv_color_t *dest_buf, lv_coord_t dest_stride, const lv_area_t *fill_area,
lv_color_t color);
static void lv_draw_n9h30_ge2d_blend_map(lv_color_t *dest_buf, const lv_area_t *dest_area, lv_coord_t dest_stride,
const lv_color_t *src_buf, lv_coord_t src_stride, lv_opa_t opa);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Turn on the peripheral and set output color mode, this only needs to be done once
*/
void lv_draw_n9h30_ge2d_ctx_init(lv_disp_drv_t *drv, lv_draw_ctx_t *draw_ctx)
{
lv_draw_sw_init_ctx(drv, draw_ctx);
lv_draw_n9h30_ge2d_ctx_t *ge2d_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx;
ge2d_draw_ctx->blend = lv_draw_n9h30_ge2d_blend;
ge2d_draw_ctx->base_draw.wait_for_finish = lv_gpu_n9h30_ge2d_wait_cb;
}
void lv_draw_n9h30_ge2d_ctx_deinit(lv_disp_drv_t *drv, lv_draw_ctx_t *draw_ctx)
{
LV_UNUSED(drv);
LV_UNUSED(draw_ctx);
}
void lv_draw_n9h30_ge2d_blend(lv_draw_ctx_t *draw_ctx, const lv_draw_sw_blend_dsc_t *dsc)
{
lv_area_t blend_area;
int32_t blend_area_w;
bool done = false;
if (!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) return;
blend_area_w = lv_area_get_width(&blend_area);
if ((lv_area_get_size(&blend_area) > 7200) &&
(((blend_area_w * (LV_COLOR_DEPTH / 2)) & 0x3) == 0) &&
(dsc->mask_buf == NULL) && (dsc->blend_mode == LV_BLEND_MODE_NORMAL))
{
lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
lv_color_t *dest_buf = draw_ctx->buf;
dest_buf += dest_stride * (blend_area.y1 - draw_ctx->buf_area->y1) + (blend_area.x1 - draw_ctx->buf_area->x1);
const lv_color_t *src_buf = dsc->src_buf;
if (src_buf)
{
lv_coord_t src_stride;
src_stride = lv_area_get_width(dsc->blend_area);
src_buf += src_stride * (blend_area.y1 - dsc->blend_area->y1) + (blend_area.x1 - dsc->blend_area->x1);
lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
lv_draw_n9h30_ge2d_blend_map(dest_buf, &blend_area, dest_stride, src_buf, src_stride, dsc->opa);
done = true;
}
else if (dsc->opa >= LV_OPA_MAX)
{
lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
lv_draw_n9h30_ge2d_blend_fill(dest_buf, dest_stride, &blend_area, dsc->color);
done = true;
}
}
if (!done) lv_draw_sw_blend_basic(draw_ctx, dsc);
}
static void lv_draw_n9h30_ge2d_blend_fill(lv_color_t *dest_buf, lv_coord_t dest_stride, const lv_area_t *fill_area,
lv_color_t color)
{
int32_t fill_area_w = lv_area_get_width(fill_area);
int32_t fill_area_h = lv_area_get_height(fill_area);
lv_color_t *start_buf = dest_buf - (fill_area->y1 * dest_stride) - fill_area->x1;
//rt_kprintf("[blend_fill %d %08x] %dx%d %d %d\n", lv_area_get_size(fill_area), dest_buf, fill_area_w, fill_area_h, fill_area->x1, fill_area->y1 );
if (IS_CACHEABLE_VRAM(dest_buf))
mmu_clean_invalidated_dcache((uint32_t)dest_buf, sizeof(lv_color_t) * (dest_stride * fill_area_h + fill_area_w));
/*Hardware filling*/
// Enter GE2D ->
ge2dInit(sizeof(lv_color_t) * 8, dest_stride, fill_area->y2, (void *)start_buf);
ge2dClip_SetClip(fill_area->x1, fill_area->y1, fill_area->x2, fill_area->y2);
if (sizeof(lv_color_t) == 4)
ge2dFill_Solid(fill_area->x1, fill_area->y1, fill_area_w, fill_area_h, color.full);
else if (sizeof(lv_color_t) == 2)
ge2dFill_Solid_RGB565(fill_area->x1, fill_area->y1, fill_area_w, fill_area_h, color.full);
ge2dClip_SetClip(-1, 0, 0, 0);
// -> Leave GE2D
}
static void lv_draw_n9h30_ge2d_blend_map(lv_color_t *dest_buf, const lv_area_t *dest_area, lv_coord_t dest_stride,
const lv_color_t *src_buf, lv_coord_t src_stride, lv_opa_t opa)
{
/*Simple copy*/
int32_t dest_x = dest_area->x1;
int32_t dest_y = dest_area->y1;
int32_t dest_w = lv_area_get_width(dest_area);
int32_t dest_h = lv_area_get_height(dest_area);
const lv_color_t *dest_start_buf = dest_buf - (dest_area->y1 * dest_stride) - dest_area->x1;
//rt_kprintf("[blend_map %d %08x -> %08x] (x:%d y:%d, %dx%d) <stride src:%d dst:%d>\n", lv_area_get_size(dest_area), src_buf, dest_buf, dest_x, dest_y, dest_w, dest_h, src_stride, dest_stride);
// Enter GE2D ->
ge2dInit(sizeof(lv_color_t) * 8, dest_stride, dest_area->y2, (void *)dest_start_buf);
if (opa >= LV_OPA_MAX)
{
ge2dBitblt_SetAlphaMode(0, 0, 0);
ge2dBitblt_SetDrawMode(0, 0, 0);
}
else
{
ge2dBitblt_SetAlphaMode(1, opa, opa);
}
// flush
mmu_clean_dcache((uint32_t)src_buf, sizeof(lv_color_t) * (src_stride * dest_h + dest_w));
ge2dSpriteBlt_Screen(dest_x, dest_y, dest_w, dest_h, (void *)src_buf);
// -> Leave GE2D
}
void lv_gpu_n9h30_ge2d_wait_cb(lv_draw_ctx_t *draw_ctx)
{
lv_draw_sw_wait_for_finish(draw_ctx);
}
/**********************
* STATIC FUNCTIONS
**********************/
#endif // #if (LV_USE_GPU_N9H30_GE2D && LV_VERSION_CHECK(8, 2, 0))
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-3-29 Wayne The first version
*/
#ifndef LV_GPU_N9H_GE2D_H
#define LV_GPU_N9H_GE2D_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../misc/lv_color.h"
#include "../../hal/lv_hal_disp.h"
#include "../sw/lv_draw_sw.h"
#if LV_USE_GPU_N9H30_GE2D && LV_VERSION_CHECK(8, 2, 0)
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
struct _lv_disp_drv_t;
typedef lv_draw_sw_ctx_t lv_draw_n9h30_ge2d_ctx_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Turn on the peripheral and set output color mode, this only needs to be done once
*/
void lv_draw_n9h30_ge2d_init(void);
void lv_draw_n9h30_ge2d_ctx_init(struct _lv_disp_drv_t *drv, lv_draw_ctx_t *draw_ctx);
void lv_draw_n9h30_ge2d_ctx_deinit(struct _lv_disp_drv_t *drv, lv_draw_ctx_t *draw_ctx);
void lv_draw_n9h30_ge2d_blend(lv_draw_ctx_t *draw_ctx, const lv_draw_sw_blend_dsc_t *dsc);
void lv_gpu_n9h30_ge2d_wait_cb(lv_draw_ctx_t *draw_ctx);
/**********************
* MACROS
**********************/
#endif /*#if LV_USE_GPU_N9H30_GE2D && LV_VERSION_CHECK(8, 2, 0)*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_GPU_N9H_GE2D_H*/
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册