KDocs 研发资料库
  • 手表穿戴技术应用文档入口汇总
  • JL707N穿戴客述问题FAQ
  • 彩屏仓 硬件开发指南 与 量产作业流程规范
  • 彩屏仓 AC98N和JL701烧录升级注意事项
  • JL707 硬件开发资料
  • JL707 手表硬件设计注意事项 总结
  • 穿戴生产烧录OTA和key文件添加使用说明
  • JL707N-入门到进阶开发指导文档
  • 彩屏仓982相关
  • 彩屏仓耳机介绍
  • 杰理701_707双屏demo介绍
  • 707电子吧唧开发资料
  • GPIO相关
  • UART串口相关
  • SPI相关
  • nandflash相关
  • norflash相关
  • IIC相关
  • PWM相关
  • SD卡相关
  • 定时器TIMER
  • 文件系统接口设计说明文档
  • 音视频录像开发流程
  • rdec编码器
  • 穿戴功耗数据标准
  • 手表蓝牙开发文档
  • 701蓝牙PAN联网demo
  • BLE开发使用说明
  • 701手表2.0.0版本SDK EQ在线调试和离线调试方法 V1.1
  • JL707 手表喇叭输出声音大小评估方法 V1.0
  • JL707 手表音频EQ调试方法 V1.0
  • AC707N 手表通话写卡 软件配置方法
  • 录音功能
  • 701手表2.X.X系列SDK调试EQ配置方法及音频调试技巧V1.1
  • 701手表104版本SDK EQ在线调试和离线调试方法 V1.1
  • mic2dac示例
  • P11 SensorHub相关
  • 手表升级操作文档
  • AC707NGPU
  • DBI模块介绍
  • GPU模块介绍
  • 701N屏幕驱动配置说明
  • 701N_UI编辑工具用户手册
  • 支付宝资料
  • 支付宝硬件接入资料
  • 支付宝乘车码接入资料
  • CAT1 接入文档
  • 701N_WATCH_CAT1开发说明
  • Findmy功能
  • music模式相关
  • 707电池曲线
  • 707N内置FLASH挂载FAT文件系统251112_v1.2
  • AC707N_本地视频播放demo(AVI-MJPEG-PCM)
  • 光波导屏幕调试
  • 耳机研发和生产流程 指南
  • 707-NandFlash 代码和UI资源独立烧录方案
  • 彩屏仓时间同步补丁
  • 彩屏仓抖音点赞移植
  • 707LVGLv8双屏开发
  • 707N蓝牙互传图传demo
  • AVIPCM数据流接入AIVOICE
  • Flash分区操作demo
  • 手表发射问题
  • 701_707 双备份升级DEMO
  • 707_乘车码刷码失败问题_共性

培训-屏幕、TP驱动相关

📎 原始文档:https://www.kdocs.cn/l/cn29hOq7FTzO 培训-屏幕、TP驱动相关

LCD相关

穿戴类屏幕相关驱动包含SPI、8bit RGB、 8 bit MCU接口屏幕,我们主要使用到的屏幕是SPI接口 ,其中SPI接口又分为单线SPI 、DSP 、QSPI等接口。但是驱动屏幕的操作在701(br28)系列上

屏幕驱动差异

707系列:

使用DBI进行管理,不直接使用spi 或者rgb接口推送屏幕。
DBI 相关配置项

image

701系列:

使用IMD硬件模块进行管理推屏
IMD相关配置项
image

695 系列:

直接使用spi进行屏幕推屏驱动和操作
image

spi 硬件驱动示例

#include "system/includes.h"
#include "media/includes.h"
#include "asm/spi.h"
#include "generic/log.h"

/*
    [[[ README ]]]
    1. 本spi测试demo提供了spi.c的API使用例程,测试方式为两个spi的环回测试。
    spi1设置为主机模式,spi2设置为从机模式,spi1发送数据到spi2,然后接收spi2
    原样返回的数据,然后比较发送出去的数据与接收的数据是否一致,一致则说明
    验证通过。
    2. 本demo涉及BYTE收发测试及DMA收发测试,通过宏SPI_TEST_MODE选择。另外
    demo还涉及到spi中断中调用可用于中断的spi API的使用。
    3. spi.c的API不包含CS引脚,CS由API以外控制。
    4. 请在board_xxx.c中定义配置结构体,例如用到spi1,需要定义spi1_p_data,
    否则编译出错。
    5. spi的DMA地址需要4字节对齐。
    6. 虽然spi.c的API带有spi0,但在有挂spi flash的芯片上使用可能会出问题,
    避免使用spi0。

*/

#define SPI1_CS_OUT() \
    do { \
        JL_PORTB->DIR &= ~BIT(4); \
        JL_PORTB->DIE |= BIT(4); \
        JL_PORTB->PU &= ~BIT(4); \
        JL_PORTB->PD &= ~BIT(4); \
    } while(0)
#define SPI1_CS_L()     (JL_PORTB->OUT &= ~BIT(4))
#define SPI1_CS_H()     (JL_PORTB->OUT |= BIT(4))

#define SPI2_CS_IN() \
    do { \
        JL_PORTA->DIR |= BIT(3); \
        JL_PORTA->DIE |= BIT(3); \
        JL_PORTA->PU &= ~BIT(3); \
        JL_PORTA->PD &= ~BIT(3); \
    } while (0)
#define SPI2_READ_CS()     (JL_PORTA->IN & BIT(3))

static u8 slave_dir = 1;
static u8 spi1_send_buf[100] __attribute__((aligned(4)));
static u8 spi1_recv_buf[100] __attribute__((aligned(4)));
static u8 spi2_send_buf[100] __attribute__((aligned(4)));
static u8 spi2_recv_buf[100] __attribute__((aligned(4)));

static spi_dev spi1_hdl = 1;
static spi_dev spi2_hdl = 2;

#define SPI_TEST_BYTE_MODE      0x01
#define SPI_TEST_DMA_MODE       0x02
//测试模式选择
#define SPI_TEST_MODE           SPI_TEST_BYTE_MODE

static void my_put_u8hex(u8 b)
{
    u8 dat;
    dat = b / 16;
    if (dat >= 0 && dat <= 9) {
        putchar('0' + dat);
    } else {
        putchar('A' + dat - 10);
    }
    dat = b % 16;
    if (dat >= 0 && dat <= 9) {
        putchar('0' + dat);
    } else {
        putchar('A' + dat - 10);
    }
    putchar(' ');
}

//中断函数,需以下特殊声明
__attribute__((interrupt("")))
static void spi2_isr()
{
    static int i = 0;
    if (spi_get_pending(spi2_hdl)) {
        spi_clear_pending(spi2_hdl);
        if (SPI2_READ_CS()) {
            return;
        }
#if SPI_TEST_MODE == SPI_TEST_BYTE_MODE
        if (slave_dir == 1) {
            spi2_recv_buf[i] = spi_recv_byte_for_isr(spi2_hdl);
            spi_send_byte_for_isr(spi2_hdl, spi2_recv_buf[i]);
            i >= 100 ? i = 0 : i++;
            slave_dir = 0;
        } else {
            slave_dir = 1;
        }
#elif SPI_TEST_MODE == SPI_TEST_DMA_MODE
        if (slave_dir == 1) {
            spi_dma_set_addr_for_isr(spi2_hdl, spi2_recv_buf, 100, 0);
            slave_dir = 0;
        } else {
            slave_dir = 1;
        }
#endif
    }
}

#if 1  //仅用于spi demo,正式工程请放到board_xxx.c文件中

const struct spi_platform_data spi1_p_data = {
    .port = {
        IO_PORTB_06,    //CLK
        IO_PORTB_07,    //DO
        IO_PORTB_05,    //DI
    },
    .mode = SPI_MODE_BIDIR_1BIT,
    .clk = 1000000,
    .role = SPI_ROLE_MASTER,
};

const struct spi_platform_data spi2_p_data = {
    .port = {
        IO_PORTB_02,    //CLK
        IO_PORTB_03,    //DO
        IO_PORTB_01,    //DI
    },
    .mode = SPI_MODE_BIDIR_1BIT,
    .clk = 1000000,
    .role = SPI_ROLE_SLAVE,
};
#endif


void spi_test_main()
{
    int i;
    int err;

    spi_open(spi1_hdl);
    spi_open(spi2_hdl);
    spi_set_ie(spi2_hdl, 1);
    //配置中断优先级,中断函数
    request_irq(IRQ_SPI2_IDX, 3, spi2_isr, 0);

    SPI1_CS_OUT();
    SPI2_CS_IN();
    SPI1_CS_H();
    for (i = 0; i < 100; i++) {
        spi1_send_buf[i] = i % 26 + 'A';
        spi1_recv_buf[i] = 0;
    }
    puts(">>> spi test start\n");
#if SPI_TEST_MODE == SPI_TEST_BYTE_MODE
    SPI1_CS_L();
    for (i = 0; i < 100; i++) {
        err = spi_send_byte(spi1_hdl, spi1_send_buf[i]);
        if (err) {
            puts("spi1 byte send timeout\n");
            break;
        }
        delay(100);
        spi1_recv_buf[i] = spi_recv_byte(spi1_hdl, &err);
        if (err) {
            puts("spi1 byte recv timeout\n");
            break;
        }
        delay(100);
    }
    SPI1_CS_H();
#elif SPI_TEST_MODE == SPI_TEST_DMA_MODE
    spi_dma_set_addr_for_isr(spi2_hdl, spi2_recv_buf, 100, 1);
    SPI1_CS_L();
    err = spi_dma_send(spi1_hdl, spi1_send_buf, 100);
    if (err < 0) {
        puts("spi1 dma send timeout\n");
        goto __out_dma;
    }
    //delay(100);
    err = spi_dma_recv(spi1_hdl, spi1_recv_buf, 100);
    if (err < 0) {
        puts("spi1 dma recv timeout\n");
        goto __out_dma;
    }
    //delay(100);
__out_dma:
    SPI1_CS_H();
#endif
    puts("<<< spi test end\n");

    puts("\nspi master receivce buffer:\n");
    for (i = 0; i < 100; i++) {
        //my_put_u8hex(spi1_recv_buf[i]);
        putchar(spi1_recv_buf[i]), putchar(0x20);
        if (i % 16 == 15) {
            putchar('\n');
        }
    }
    if (i % 16) {
        putchar('\n');
    }

    if (!memcmp(spi1_send_buf, spi1_recv_buf, 100)) {
        puts("\nspi test pass\n");
    } else {
        puts("\nspi test fail\n");
    }

    spi_close(spi1_hdl);
    spi_close(spi2_hdl);
}

SPI 接口屏幕

spi 接口屏幕也是有不同的时序的,例如普通spi 屏幕就有3-wire spi /4-wire spi
例如 3-wire spi 时序如下 :
image 4-wire spi
image

通过上序时序可以, 4-wire spi 会比 3-wire spi 时序上多出一个DCX io口 ,在很多屏幕上也有别名是A0 或者RS脚。csx 主要作用是用于区分数据或者命令 。另外由于4-wire spi 多了一个IO口控制是命令或者数据,所以只需要8bit 数据即可表达RGB数据,而3-wire spi 需要 9bit 数据,用1bit 表示数据或者命令

屏幕驱动流程

以701 为例: cpu\br28\ui_driver\lcd_drive\lcd_drive.c
image 通过上面截图 lcd_drv_get_hal 获取不同屏幕驱动的指针,指针指向结构体如下:
image 初始化成功后,可以通过
void lcd_set_draw_area(int xstart, int xend, int ystart, int yend);接口进行绘制。

屏幕切线处理

基础情况屏幕产生撕裂的主要原因是追赶的问题,屏幕读数据和写入屏幕数据速度由于速度不一样,所以出现了撕裂的情况
imageimage 出现上述情况基本可能存在很多条切,或者单条切线,但是切线位置不固定

当然另外存在一种情况是切线位置固定,这个时候我们就可以通过调整屏幕 0x44 寄存器,或者个别屏幕0xc4寄存器中的te delay

TP 相关

tp工作流程:

初始化 IIC -> 读取设备ID ->检测固件是否需要升级->正常通过TP中断回调读取IIC数据 ->处理IIC 读取数据转换成单击、多击等事件->将事件和坐标信息psot 到ui task

#include "app_config.h"
#include "system/includes.h"
#include "asm/iic_hw.h"
#include "asm/iic_soft.h"
#include "asm/gpio.h"
#include "asm/mcpwm.h"
#include "bl6133.h"

#if TCFG_TOUCH_PANEL_ENABLE


#if TCFG_TP_BL6133_ENABLE
#define     SLAVE_DEV_ADDR        (0x2C<<1) //固有,不可配置,用于 chipID 读取,固件烧录操作

#ifndef abs
#define abs(x)  ((x)>0?(x):-(x) )
#endif

/*************Betterlife ic debug***********/
/* #define LOG_TAG_CONST       BL6133 */
#define LOG_TAG             "[bl6133]"
#include "debug.h"
#if defined(BL_DEBUG)
/* #define bl_log_trace        log_info */
#endif
void delay(volatile u32 t);
void udelay(u32 us);
#define   MDELAY(n)        mdelay(n)

#undef log_info
#define log_info(fmt, ...)

#include "ui/ui.h"
#include "ui/ui_api.h"

/*************Betterlife ic iic select***********/
#if TCFG_BL6133_USER_IIC_TYPE
#define iic_init(iic)                       hw_iic_init(iic)
#define iic_uninit(iic)                     hw_iic_uninit(iic)
#define iic_start(iic)                      hw_iic_start(iic)
#define iic_stop(iic)                       hw_iic_stop(iic)
#define iic_tx_byte(iic, byte)              hw_iic_tx_byte(iic, byte)
#define iic_rx_byte(iic, ack)               hw_iic_rx_byte(iic, ack)
#define iic_read_buf(iic, buf, len)         hw_iic_read_buf(iic, buf, len)
#define iic_write_buf(iic, buf, len)        hw_iic_write_buf(iic, buf, len)
#define iic_suspend(iic)                    hw_iic_suspend(iic)
#define iic_resume(iic)                     hw_iic_resume(iic)
#else
#define iic_init(iic)                       soft_iic_init(iic)
#define iic_uninit(iic)                     soft_iic_uninit(iic)
#define iic_start(iic)                      soft_iic_start(iic)
#define iic_stop(iic)                       soft_iic_stop(iic)
#define iic_tx_byte(iic, byte)              soft_iic_tx_byte(iic, byte)
#define iic_rx_byte(iic, ack)               soft_iic_rx_byte(iic, ack)
#define iic_read_buf(iic, buf, len)         soft_iic_read_buf(iic, buf, len)
#define iic_write_buf(iic, buf, len)        soft_iic_write_buf(iic, buf, len)
#define iic_suspend(iic)                    soft_iic_suspend(iic)
#define iic_resume(iic)                     soft_iic_resume(iic)
#endif

static u8 tp_last_staus = ELM_EVENT_TOUCH_UP;
static int tp_down_cnt = 0;
static int tp_int_io_init = 0;

/****************************************************/
bl6133_param bl6133_iic_info_test = {
    .iic_hdl = 0,
    .iic_delay = 1,
};
/*************************************
 *注意:
 *    bl6133触摸屏iic时钟频率必须小于200k
 * **********************************/

static bl6133_param *bl6133_iic_info;
//return =len:ok; other:fail
u16 CTP_FLASH_I2C_WRITE(u8 slave_addr, u8 *buf, u16 len)
{
    u16 i = 0;
    iic_start(bl6133_iic_info->iic_hdl);
    if (0 == iic_tx_byte(bl6133_iic_info->iic_hdl, slave_addr)) {
        iic_stop(bl6133_iic_info->iic_hdl);
        return 0;
    }

    for (i = 0; i < len; i++) {
        delay(bl6133_iic_info->iic_delay);
        if (0 == iic_tx_byte(bl6133_iic_info->iic_hdl, buf[i])) {
            iic_stop(bl6133_iic_info->iic_hdl);
            return i;
        }
    }
    iic_stop(bl6133_iic_info->iic_hdl);
    return i;
}

//return =len:ok; other:fail
u16 CTP_FLASH_I2C_READ(u8 slave_addr, u8 *buf, u16 len)
{
    u16 i = 0;
    iic_start(bl6133_iic_info->iic_hdl);
    if (0 == iic_tx_byte(bl6133_iic_info->iic_hdl, slave_addr + 1)) {
        iic_stop(bl6133_iic_info->iic_hdl);
        return 0;
    }
    for (i = 0; i < len - 1; i++) {
        delay(bl6133_iic_info->iic_delay);
        *buf++ = iic_rx_byte(bl6133_iic_info->iic_hdl, 1);
    }
    i++;
    *buf = iic_rx_byte(bl6133_iic_info->iic_hdl, 0);
    iic_stop(bl6133_iic_info->iic_hdl);
    return i;
}

void ctp_delay_us(unsigned int time)
{
    udelay(time);
}
void ctp_delay_ms(unsigned short time)
{
    mdelay(time);
}


void bl_ts_set_intmode(char mode)
{
    if (0 == mode) {
        //GPIO mode
        CTP_SET_I2C_EINT_OUTPUT;
    } else if (1 == mode) {
        //INT mode
        CTP_SET_I2C_EINT_INPUT;
    }
}

void bl_ts_set_intup(char level)
{
    if (level == 1) {
        CTP_SET_I2C_EINT_HIGH;
    } else if (level == 0) {
        CTP_SET_I2C_EINT_LOW;
    }
}

#ifdef INT_PIN_WAKEUP
void bl_ts_int_wakeup(void)
{
    bl_ts_set_intmode(0);
    bl_ts_set_intup(1);
    ctp_delay_ms(20);
    bl_ts_set_intup(0);
    ctp_delay_ms(1);
    bl_ts_set_intup(1);
    ctp_delay_ms(20);
    bl_ts_set_intmode(1);
}
#endif

#ifdef  RESET_PIN_WAKEUP
void bl_ts_reset_wakeup(void)
{
    //    CTP_SET_RESET_PIN_OUTPUT;
    CTP_SET_RESET_PIN_LOW;
    ctp_delay_ms(1);
    CTP_SET_RESET_PIN_HIGH;
    ctp_delay_ms(20);
    CTP_SET_RESET_PIN_LOW;
    ctp_delay_ms(20);
    CTP_SET_RESET_PIN_HIGH;

    gpio_set_hd0(CTP_RESET_PIN, 0);
    //    ctp_delay_ms(20);
}
void bl_ts_reset(void)
{
    //    CTP_SET_RESET_PIN_OUTPUT;
    CTP_SET_RESET_PIN_LOW;
    ctp_delay_ms(10);
    CTP_SET_RESET_PIN_HIGH;
    ctp_delay_ms(100);

    gpio_set_hd0(CTP_RESET_PIN, 0);
}
#endif

int Check_bl6133_id(unsigned char *buf)
{
    int ret = 0x00;
    for (uint8_t t = 0; t < 3; t++) {
        bl_ts_reset();
        bl_ts_set_intup(0);
        ctp_delay_ms(50);
        uint8_t sendata[] = {0x0a, 0xf5, 0xe7, 0xe8};
        ret = CTP_FLASH_I2C_WRITE(SLAVE_DEV_ADDR, sendata, 4);
        if (ret != 4) {
            log_error("bl_get_chip_id:i2c write flash error___\n");
            ret = -1;
        }
        ret = CTP_FLASH_I2C_READ(SLAVE_DEV_ADDR, buf, 1);
        if (ret != 1) {
            log_error("bl_get_chip_id:i2c read flash error___\n");
            ret = -1;
        }
        if (*buf == 0x22) {
            bl_ts_reset_wakeup();
            log_info("TP_BL6133_CHIP_ID = 0x%02x, check: Pass\r\n", *buf);
            return 0;
        }
        ctp_delay_ms(20);
    }
    return ret;
}

unsigned char ctp_bl_ts_init(void)
{
    uint32_t s;
#ifdef  BTL_CHECK_CHIPID
    unsigned char chipID = 0x00;
#endif
    char  ret = 0;
#ifdef  RESET_PIN_WAKEUP
#ifndef BTL_CHECK_CHIPID // 读id里面有reset
    //bl_ts_reset_wakeup();
    bl_ts_reset();
#endif /* #ifndef BTL_CHECK_CHIPID */
#endif
    /* #ifdef INT_PIN_WAKEUP */
    /*     bl_ts_int_wakeup(); */
    /* #endif */
    MDELAY(20);

#ifdef  BTL_CHECK_CHIPID
    bl_ts_set_intmode(0);
    bl_ts_set_intup(0);
    //ret = bl_get_chip_id(&chipID);
    ret = Check_bl6133_id(&chipID);
    bl_ts_set_intup(1);
    bl_ts_set_intmode(1);
    if (ret < 0) {
        log_error("I2C communication ERROR!");
        return false;
    } else if (chipID != BTL_FLASH_ID) {
        log_error("Please specify the IC model:0x%x!", chipID);
        return false;
    } else {
        log_info("I2C communication success:chipID = %x!", chipID);
    }
    MDELAY(10);
#endif
#ifdef  BL_AUTO_UPDATE_FARMWARE
    extern int bl_auto_update_fw(void);
    //    s = os_lock();////////
    wdt_disable();
    bl_ts_set_intmode(0);
    bl_ts_set_intup(0);
    bl_auto_update_fw();
    ctp_delay_ms(5);
    bl_ts_set_intup(1);
    bl_ts_set_intmode(1);
    wdt_enable();
    //    os_unlock(s);////////
#endif
    return true;
}

//iic scl:<=200KHz
bool ctp_init_bl6133(void *priv)
{
    if (priv == NULL) {
        log_error("ctp bl6133 priv ERROR!");
        return false;
    }
    bl6133_iic_info = (bl6133_param *)priv;
    bool ret = false;

    log_info("the iic speed of ctp-bl6133 must be set below 200k(iic<=200k)!");
    bl_ts_set_intmode(1);
    CTP_SET_RESET_PIN_OUTPUT;
    /* iic_init(bl6133_iic_info->iic_hdl); */
    ret = ctp_bl_ts_init();
    return ret;
}


void ctp_sleep_bl6133(void)
{
    unsigned char data = 0;
    unsigned char aa = 0, bb = 0;

    unsigned char sleepCmd[] = {0xa5, 0x03};
    CTP_FLASH_I2C_WRITE(SLAVE_DEV_ADDR, sleepCmd, 1);
    CTP_FLASH_I2C_READ(SLAVE_DEV_ADDR, &aa, 1);

    MDELAY(10);
    bb = CTP_FLASH_I2C_WRITE(SLAVE_DEV_ADDR, sleepCmd, sizeof(sleepCmd));
    log_info("ctp_sleep_bl6133 aa=%d,bb=%d", aa, bb);
    // MDELAY(100); //和显示屏共用delay耗时

    /* #ifdef INT_PIN_WAKEUP */
    /*     bl_ts_set_intmode(0); */
    /*     bl_ts_set_intup(1); */
    /* #endif */

    log_info("ctp_sleep_bl6133");
}

void ctp_wakeup_bl6133(void)
{
#ifdef  RESET_PIN_WAKEUP
    bl_ts_reset_wakeup();
#endif
    /* #ifdef INT_PIN_WAKEUP */
    /*     bl_ts_int_wakeup(); */
    /* #endif */
    bl_ts_set_intmode(1);//开io中断
    log_info("ctp_wakeup_bl6133");
}

//void ctp_pad_enter_dlps_bl6133(void){
//    Pad_Config(ABH_DRV_PIN_NUM_TP_INT, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_LOW);
//    Pad_Config(ABH_DRV_PIN_NUM_TP_RST, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_LOW);
//}

//void ctp_pad_exit_dlps_bl6133(void){
//    Pad_Config(ABH_DRV_PIN_NUM_TP_INT, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_LOW);
//  Pad_Config(ABH_DRV_PIN_NUM_TP_RST, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_ENABLE, PAD_OUT_HIGH);
//}


void ctp_enter_low_power(void)
{
    unsigned char data = 0;
    unsigned char aa = 0, bb = 0;

    unsigned char sleepCmd[] = {0xa5, 0x01};
    CTP_FLASH_I2C_WRITE(CTP_SLAVE_ADDR, sleepCmd, 1);
    CTP_FLASH_I2C_READ(CTP_SLAVE_ADDR, &aa, 1);

    MDELAY(10);
    bb = CTP_FLASH_I2C_WRITE(CTP_SLAVE_ADDR, sleepCmd, sizeof(sleepCmd));
    log_info("ctp_enter_low_power aa=%d,bb=%d", aa, bb);
    // MDELAY(100); //和显示屏共用delay耗时

    log_info("ctp_enter_low_power");
}

void ctp_exit_low_power(void)
{
#ifdef  RESET_PIN_WAKEUP
    bl_ts_reset_wakeup();
#endif
    /* #ifdef INT_PIN_WAKEUP */
    /*     bl_ts_int_wakeup(); */
    /* #endif */
    log_info("ctp_exit_low_power");
}


int ctp_poweron(void)
{
    //poweron
    if (TCFG_TP_POWER_IO == NO_CONFIG_PORT) {
        return -1;
    }
    printf("ctp power on\n");
    gpio_direction_output(TCFG_TP_POWER_IO, 1);

    u32 tp_io_table[2] = {TCFG_TP_RESET_IO, TCFG_TP_INT_IO};

    int i;
    for (i = 0; i < sizeof(tp_io_table) / sizeof(tp_io_table[0]); i++) {
        gpio_set_die(tp_io_table[i], 1);
    }
    gpio_direction_output(TCFG_TP_RESET_IO, 0);
    iic_init(bl6133_iic_info->iic_hdl);

    tp_last_staus = ELM_EVENT_TOUCH_UP;
    tp_down_cnt = 0;

    return 0;
}


int ctp_poweroff(void)
{
    //poweroff
    if (TCFG_TP_POWER_IO == NO_CONFIG_PORT) {
        return -1;
    }
    printf("ctp power off\n");

    power_wakeup_index_enable(1, false);//中断禁止

    gpio_direction_output(TCFG_TP_POWER_IO, 0);

    u32 tp_io_table[2] = {TCFG_TP_RESET_IO, TCFG_TP_INT_IO};

    int i;
    for (i = 0; i < sizeof(tp_io_table) / sizeof(tp_io_table[0]); i++) {
        gpio_direction_input(tp_io_table[i]);
        gpio_set_pull_up(tp_io_table[i], 0);
        gpio_set_pull_down(tp_io_table[i], 0);
        gpio_set_die(tp_io_table[i], 0);
    }

    iic_uninit(bl6133_iic_info->iic_hdl);

    return 0;
}

void ctp_enter_sleep(void)
{
    ctp_sleep_bl6133();
}
void ctp_exit_sleep(void)
{
    ctp_wakeup_bl6133();
}

#define ENERGY_XDISTANCE    15
#define ENERGY_YDISTANCE    15
#define ENERGY_TIME            20 //ms
struct touch_kinetic_energy {
    int t1;
    int x1;
    int y1;

    int t2;
    int x2;
    int y2;
};
static struct touch_kinetic_energy tke = {0};
static void tke_start(int x, int y)
{
    memcpy(&tke.t2, &tke.t1, sizeof(tke) / 2);

    if ((tke.x1 == x) && (tke.y1 == y)) {
        tke.t1 = tke.t1;
    } else {
        tke.t1 = jiffies_msec();
    }
    tke.x1 = x;
    tke.y1 = y;
    /* printf("tke start %d, %d, %d\n", tke.t1, tke.x1, tke.y1); */
}

static void tke_stop(int x, int y, struct touch_event *up_t)
{
    struct touch_event t = {0};
    u8 xdir, ydir;

    if (tke.t1 == 0) {
        //在这里发送up消息,因为没有惯性,所以直接发送
        ui_touch_msg_post(up_t);
        return;
    }
    tke.t1 = tke.t1 - tke.t2;
    tke.x1 = tke.x1 - tke.x2;
    tke.y1 = tke.y1 - tke.y2;

    /* printf("tke end %d, %d, %d\n", tke.t1, tke.x1, tke.y1); */

    if ((tke.t1 < ENERGY_TIME) &&
        ((abs(tke.x1) > ENERGY_XDISTANCE) || abs(tke.y1) > ENERGY_YDISTANCE)) {

        //在这里发送up消息,并附上有惯性能量标志
        up_t->has_energy = 1;
        ui_touch_msg_post(up_t);

        if (abs(tke.x1) <= ENERGY_XDISTANCE) {
            tke.x1 = 0;
        }
        if (abs(tke.y1) <= ENERGY_YDISTANCE) {
            tke.y1 = 0;
        }
        xdir = (tke.x1 < 0) ? 1 : 2;
        ydir = (tke.y1 < 0) ? 1 : 2;
        /* printf("xdir %d, ydir %d\n", xdir, ydir); */

        t.event = ELM_EVENT_TOUCH_ENERGY;
        t.x = (tke.x1 << 16) | (tke.t1 & 0xffff);
        t.y = (tke.y1 << 16) | (ydir << 8) | (xdir & 0xff);
        ui_touch_msg_post(&t);

        /* printf("tke out %d, %d, %d, %d, %d\n", (t.x & 0xffff), (t.x >> 16), (t.y >> 16), (t.y & 0xff), (t.y >> 8) & 0xff); */

    } else {
        //在这里发送up消息,因为没有惯性,所以直接发送
        ui_touch_msg_post(up_t);
    }

    memset(&tke, 0, sizeof(tke));

}


struct touch_info {
    int y;
    int x;
    int p;
    int id;
    int count;
};

#define Y_MIRROR  0
#define X_MIRROR  0
#define VK_Y              454
#define VK_X              454
#define VK_Y_MOVE       100//227
#define VK_X_MOVE          100//227
#define VK_X_Y_DIFF        47
#define X_SINGLE_MOVE   0 //单次滑动距离上限阈值,用于过滤多点触摸时误发L/R_MOVE事件 0 关闭 ;阈值,根据tp实际情况调整
#define Y_SINGLE_MOVE   0 //y方向过滤
/* struct touch_event { */
/*     int event; */
/*     int x; */
/*     int y; */
/* }; */



#define abs(x)  ((x)>0?(x):-(x) )

static void tpd_down(int raw_x, int raw_y, int x, int y, int p)
{
    struct touch_event t = {0};
    static int first_x = 0;
    static int first_y = 0;
#if (X_SINGLE_MOVE && Y_SINGLE_MOVE)
    static s16 last_x = 0;
    static s16 last_y = 0;
    static s16 dist_x = 0;
    static s16 dist_y = 0;
#endif
    static u8 move_flag = 0;

    if (x < 0) {
        x = 0;
    }
    if (x > (VK_X - 1)) {
        x = VK_X - 1;
    }
    if (y < 0) {
        y = 0;
    }
    if (y > (VK_Y - 1)) {
        y = VK_Y - 1;
    }
#if Y_MIRROR
    x = VK_X - x - 1;
#endif

#if X_MIRROR
    y = VK_Y - y - 1;
#endif

    if ((tp_last_staus == ELM_EVENT_TOUCH_DOWN) && (x == first_x) && (y == first_y)) {
        tp_down_cnt++;
        if (tp_down_cnt < 30) {
            return;
        }
        tp_last_staus = ELM_EVENT_TOUCH_HOLD;
        tp_down_cnt = 0;

        t.event = tp_last_staus;
        t.x = x;
        t.y = y;
        log_info("----tpd_hold----");
        ui_touch_msg_post(&t);
        return;
    }

    /* log_info("D[%4d %4d %4d]\n", x, y, p); */
    //log_info("tp_last_status:%d mf:%d x(%d->%d=%d:%d:%d),y(%d->%d=%d:%d:%d)",tp_last_staus,move_flag,first_x,x,x - first_x,last_x,dist_x,first_y,y,y-first_y,last_y,dist_y);
    if (tp_last_staus != ELM_EVENT_TOUCH_UP) {
        int x_move = abs(x - first_x);
        int y_move = abs(y - first_y);
#if (X_SINGLE_MOVE && Y_SINGLE_MOVE)
        int x_last_move = (x - last_x);
        int y_last_move = (y - last_y);
        if (!move_flag && (abs(dist_x) >= VK_X_MOVE || abs(dist_y) >= VK_Y_MOVE) && (abs(abs(dist_x) - abs(dist_y)) >= VK_X_Y_DIFF)) {
            if (abs(dist_x)  > abs(dist_y)) {
                if (dist_x > 0) {
                    tp_last_staus = ELM_EVENT_TOUCH_R_MOVE;
                    log_info("----tpd_rigth_move----");
                } else {
                    tp_last_staus = ELM_EVENT_TOUCH_L_MOVE;
                    log_info("----tpd_left_move----");
                }

            } else {
                if (dist_y > 0) {
                    tp_last_staus = ELM_EVENT_TOUCH_D_MOVE;
                    log_info("----tpd_down_move----");
                } else {
                    tp_last_staus = ELM_EVENT_TOUCH_U_MOVE;
                    log_info("----tpd_up_move----");
                }
            }
            last_x = x;
            last_y = y;
            dist_x += x_last_move;
            dist_y += y_last_move;
            move_flag = 1;
#else
        if (!move_flag && (x_move >= VK_X_MOVE || y_move >= VK_Y_MOVE) && (abs(x_move - y_move) >= VK_X_Y_DIFF)) {
            if (x_move > y_move) {
                if (x > first_x) {
                    tp_last_staus = ELM_EVENT_TOUCH_R_MOVE;
                    log_info("----tpd_rigth_move----");
                } else {
                    tp_last_staus = ELM_EVENT_TOUCH_L_MOVE;
                    log_info("----tpd_left_move----");
                }

            } else {

                if (y > first_y) {
                    tp_last_staus = ELM_EVENT_TOUCH_D_MOVE;
                    log_info("----tpd_down_move----");
                } else {
                    tp_last_staus = ELM_EVENT_TOUCH_U_MOVE;
                    log_info("----tpd_up_move----");
                }
            }
            move_flag = 1;
#endif

        } else {
            if ((x == first_x) && (y == first_y)) {
                return;
            }
#if (X_SINGLE_MOVE && Y_SINGLE_MOVE)
            if ((abs(x_last_move) > X_SINGLE_MOVE) || (abs(y_last_move) > Y_SINGLE_MOVE)) {
                return;
            }
            last_x = x;
            last_y = y;
            dist_x += x_last_move;
            dist_y += y_last_move;
#endif
            tp_last_staus = ELM_EVENT_TOUCH_MOVE;
            log_info("----tpd_move----");
        }
        /* tp_last_staus = ELM_EVENT_TOUCH_HOLD; */
        tke_start(x, y);
    } else {
#if (X_SINGLE_MOVE && Y_SINGLE_MOVE)
        if (tp_last_staus != ELM_EVENT_TOUCH_UP) {
            return;
        }
        tp_last_staus = ELM_EVENT_TOUCH_DOWN;
        first_x = x;
        first_y = y;
        last_x = x;
        last_y = y;
        dist_x = 0;
        dist_y = 0;
#else
        tp_last_staus = ELM_EVENT_TOUCH_DOWN;
        first_x = x;
        first_y = y;
#endif
        move_flag = 0;
        log_info("----tpd_down----");
    }

    t.event = tp_last_staus;
    t.x = x;
    t.y = y;
    ui_touch_msg_post(&t);
}

static void tpd_up(int raw_x, int raw_y, int x, int y, int p)
{
    struct touch_event t = {0};

    if (x < 0) {
        x = 0;
    }
    if (x > (VK_X - 1)) {
        x = VK_X - 1;
    }
    if (y < 0) {
        y = 0;
    }
    if (y > (VK_Y - 1)) {
        y = VK_Y - 1;
    }

#if Y_MIRROR
    x = VK_X - x - 1;
#endif

#if X_MIRROR
    y = VK_Y - y - 1;
#endif

    /* log_info("U[%4d %4d %4d]\n", x, y, 0); */
    tp_last_staus = ELM_EVENT_TOUCH_UP;
    tp_down_cnt = 0;
    t.event = tp_last_staus;
    t.x = x;
    t.y = y;
    log_info("----tpd_up----");
    //不在这里发送up消息,在tke_stop里面!!!
    /* ui_touch_msg_post(&t); */

    tke_stop(x, y, &t);
}


u8 get_ctp_bl6133_info(struct touch_info *cinfo)
{
    static uint8_t keep_times = 0;
    uint8_t  lvalue[2 + MAX_POINT_NUM * 6];
    uint16_t pdwSampleX, pdwSampleY;
    unsigned char cmdPoint = 0x01;


    CTP_FLASH_I2C_WRITE(SLAVE_DEV_ADDR, &cmdPoint, sizeof(cmdPoint));
    CTP_FLASH_I2C_READ(SLAVE_DEV_ADDR,  lvalue, sizeof(lvalue));

    pdwSampleX = (((unsigned short)(lvalue[2] & 0x0f)) << 8) | lvalue[3];
    pdwSampleY = (((unsigned short)(lvalue[4] & 0x0f)) << 8) | lvalue[5];

    //BI6133_evt_handle(((lvalue[2]&0xc0)>>6),lvalue[0],pdwSampleX,pdwSampleY);
    uint8_t status;
    u8 touchAction = 0;
    status = ((lvalue[2] & 0xc0) >> 6);

    /* log_info("coordinate move:%d statu:%d , x=%d, y=%d",lvalue[0],status, pdwSampleX, pdwSampleY); */
    cinfo->p = status; //event flag
    cinfo->x = pdwSampleX;
    cinfo->y = pdwSampleY;
    //    if (status == 1) { // Touched
    /* if (status == 0 || status == 2) { // Touched */
    /*     if (gTouched) */
    /*         touchAction = CD_TOUCH_MOVE; */
    /*     else */
    /*         touchAction = CD_TOUCH_DOWN; */
    /*     gTouched = true; */
    /* } else { // Not touched */
    /*     if (gTouched) */
    /*         touchAction = CD_TOUCH_UP; */
    /*     else */
    /*         touchAction = CD_TOUCH_NONE; */
    /*     gTouched = false; */
    /* } */
    /* if (touchAction != CD_TOUCH_NONE) {     */
    /*     //log_info("touchAction=%d", touchAction); */
    /* } */
    return true;
}



static bool touch_flag = 0;
static bool touch_event_polling_flag = 0; //bl6133不支持
bool BL6133_ID_G_MODE = 1; //bl6133不支持
static int touch_event_handler();
#ifdef CONFIG_CPU_BR23
static int touch_int_handler()
{
    touch_flag = 1;
    if (BL6133_ID_G_MODE) {
        touch_event_handler();
    } else {
        touch_event_polling_flag = 1;
    }
    return 0;
}
#elif defined(CONFIG_CPU_BR28)||defined(CONFIG_CPU_BR27)

static void touch_int_handler(u8 index, u8 gpio)
{
    if (gpio != CTP_EINT_PIN) {
        return ;
    }

    touch_flag = 1;
    if (BL6133_ID_G_MODE) {
        touch_event_handler();
    } else {
        touch_event_polling_flag = 1;
    }
}
#endif


static int touch_event_handler()
{
    struct touch_info cinfo;
    int i = 0;
    int last_ms = 0 ;
    if (!touch_flag) {
        return 0;
    }
    if(jiffies_msec() - last_ms < 20){
        printf("usr return tp msg !!!\n");
        return 0;
    }
    touch_flag = 0;

    if (get_ctp_bl6133_info(&cinfo)) {
        if (cinfo.p == 0 || cinfo.p == 2) {
            tpd_down(cinfo.x, cinfo.y, cinfo.x, cinfo.y, 0);
        } else {
            tpd_up(cinfo.x, cinfo.y, cinfo.x, cinfo.y, 0);
        }
        last_ms = jiffies_msec();
//fun test
        log_info("coordinate move: statu: , x=%d, y=%d", cinfo.x, cinfo.y);
        /* if(cinfo.x>400){ */
        /*     ctp_enter_low_power(); */
        /* }else if(cinfo.x<50){ */
        /*     ctp_exit_low_power(); */
        /* } */
        /* if(cinfo.y>400){ */
        /*     ctp_sleep_bl6133(); */
        /* }else if(cinfo.y<50){ */
        /*     ctp_wakeup_bl6133(); */
        /* } */
    }
    return 0;
}
/* void touch_event_polling() */
/* { */
/*     if(touch_event_polling_flag){ */
/*         touch_flag = 1; */
/*         touch_event_handler(); */
/*         if(BL6133_INT_R()==1){ */
/*             touch_event_polling_flag=0; */
/*         } */
/*     } */
/* } */
/* int BL6133_id_g_mode(u8 mode)//1:trigger, 0:polling */
/* { */
/*     u8 data_w[2]={FTS_REG_ID_G_MODE,mode}; */
/*     int res =0; */
/*     res=tpd_i2c_write(data_w, 2); */
/*     if(res!=2){ */
/*         log_error("set id_g_mode fail!"); */
/*     } */
/*     return res; */
/* } */



void ui_set_touch_event(void (*touch_event)(void *priv), int interval);

extern void port_wkup_interrupt_init(u32 port, u8 trigger_edge, void (*cbfun)(void));
void bl6133_int_en()
{
    /* log_info("-------------------port wkup isr---------------------------"); */
#ifdef CONFIG_CPU_BR23
    io_ext_interrupt_init(CTP_EINT_PIN, 1, touch_int_handler);
#elif defined(CONFIG_CPU_BR28)
    // br28外部中断回调函数,按照现在的外部中断注册方式
    // io配置在板级,定义在板级头文件,这里只是注册回调函数
    if (tp_int_io_init == 0) {
        port_edge_wkup_set_callback_by_index(1, touch_int_handler); // 序号需要和板级配置中的wk_param对应上
        tp_int_io_init = 1;
    } else {
        power_wakeup_index_enable(1, true);//中断使能
    }
#elif defined(CONFIG_CPU_BR27)
    port_edge_wkup_set_callback(touch_int_handler);
#endif
    /* if (BL6133_ID_G_MODE == 0) { */
    /*     //定时执行touch_event_polling(); */
    /*     sys_timer_add((void *)NULL, touch_event_polling, 20); //注册按键扫描定时器 */
    /* } */

    /* sys_timer_add((void *)NULL, touch_event_handler, 20); //注册按键扫描定时器 */
#if TCFG_UI_ENABLE
    ui_set_touch_event(NULL, 0);
#endif
}




void bl6133_test()
{
    iic_init(bl6133_iic_info_test.iic_hdl);
    if (ctp_init_bl6133(&bl6133_iic_info_test) == true) {
        /* bl6133_int_en(); */
        log_info("bl6133 init ok!");
    } else {
        log_error("bl6133 init fail!");
    }
}

/**************************test**************************/
#if 0
void bl6133_test1()
{
    iic_init(bl6133_iic_info_test.iic_hdl);

    if (ctp_init_bl6133(&bl6133_iic_info_test) == true) {
        log_info("-------------------port wkup isr---------------------------");
        bl6133_int_en();
        /* port_wkup_enable(IO_PORTA_04, 1, touch_int_handler); //PA08-IO中断,1:下降沿触发,回调函数port_wkup_irq_cbfun_test */
        log_info("bl6133 init ok!");
    } else {
        log_error("bl6133 init fail!");
    }
}

#endif
#endif

#endif



image

常见屏幕驱动

屏幕触摸驱动相关参考.otl