添加表冠(Encoder)支持
authorSnickerSun <snickersun@163.com>
Sat, 17 Feb 2024 04:10:31 +0000 (12:10 +0800)
committerSnickerSun <snickersun@163.com>
Sat, 17 Feb 2024 04:10:31 +0000 (12:10 +0800)
26 files changed:
code/sdk/application/brandy/brandy_recovery/input_app.h
code/sdk/application/brandy/brandy_standard/input_app.h
code/sdk/application/brandy/brandy_testsuite/input_app.h
code/sdk/application/wearable/service/power_manager/src/actions/display_action.c
code/sdk/drivers/peripheral/rotary_encoder/CMakeLists.txt
code/sdk/drivers/peripheral/rotary_encoder/hx3507/hx3507.c [new file with mode: 0644]
code/sdk/drivers/peripheral/rotary_encoder/hx3507/hx3507.h [new file with mode: 0644]
code/sdk/drivers/peripheral/rotary_encoder/hx3507/hx3507_at_cmd.c [new file with mode: 0644]
code/sdk/drivers/peripheral/rotary_encoder/hx3507/hx3507_at_cmd.h [new file with mode: 0644]
code/sdk/drivers/peripheral/rotary_encoder/hx3507/hx3507_hal.c [new file with mode: 0644]
code/sdk/drivers/peripheral/rotary_encoder/hx3507/hx3507_hal.h [new file with mode: 0644]
code/sdk/drivers/peripheral/rotary_encoder/rotary_encoder_def.h [new file with mode: 0644]
code/sdk/drivers/peripheral/rotary_encoder/rotary_encoder_drv.c [new file with mode: 0644]
code/sdk/drivers/peripheral/rotary_encoder/rotary_encoder_drv.h [new file with mode: 0644]
code/sdk/drivers/peripheral/rotary_encoder/rotary_encoder_queue1.c [new file with mode: 0644]
code/sdk/drivers/peripheral/rotary_encoder/rotary_encoder_queue1.h [new file with mode: 0644]
code/sdk/drivers/peripheral/touch/ft6x46_touch/ft6x46_ctrl.c
code/sdk/drivers/peripheral/touch/ft6x46_touch/ft6x46_ctrl.h
code/sdk/drivers/peripheral/touch/touch_screen_def.h
code/sdk/drivers/peripheral/touch/touch_screen_drv.c
code/sdk/middleware/services/gui/hal/input/src/input_manager.c
code/sdk/middleware/services/gui/uikit/proprietary/src/ui/frameworks/dock/lite_encoder_device.cpp [new file with mode: 0644]
code/sdk/middleware/services/gui/uikit/proprietary/src/ui/frameworks/dock/lite_encoder_device.h [new file with mode: 0644]
code/sdk/middleware/services/gui/uikit/proprietary/src/utils/frameworks/hals/lite_input_distributer.cpp
code/sdk/middleware/services/gui/uikit/proprietary/src/utils/frameworks/hals/lite_input_hal.cpp
code/sdk/middleware/services/gui/uikit/proprietary/src/utils/innerkits/hals/lite_input_distributer.h

index 81bdeff..918ec12 100755 (executable)
@@ -103,6 +103,7 @@ typedef enum {
 typedef enum {
     APP_BUTTON,
     APP_TOUCH,
+    APP_ENCODER,
 } app_type;
 
 typedef struct {
index 81bdeff..918ec12 100755 (executable)
@@ -103,6 +103,7 @@ typedef enum {
 typedef enum {
     APP_BUTTON,
     APP_TOUCH,
+    APP_ENCODER,
 } app_type;
 
 typedef struct {
index 3def5b7..473eb65 100755 (executable)
@@ -98,6 +98,7 @@ typedef enum {
 typedef enum {
     APP_BUTTON,
     APP_TOUCH,
+    APP_ENCODER,
 } app_type;
 
 typedef struct {
index 3a0ffcf..746856f 100755 (executable)
@@ -28,6 +28,7 @@
 #endif
 #include "sys/time.h"
 #include "touch_screen_def.h"
+#include "rotary_encoder_def.h"
 #include "time.h"
 #include "tcxo.h"
 #ifdef CONFIG_LOW_POWER_TEST
@@ -156,6 +157,7 @@ static uint32_t action_display_lcd_on()
 #endif
     if ((g_pms_lcd_on_first_flag == false) && (g_pms_dpu_ready == false)) {
         touch_screen_resume(); // open touch
+        rotary_encoder_resume();
     }
 #ifdef CONFIG_CLDO1PD_SUPPORT
     pmu_control_cldo1_sleep_bypass(TURN_ON);
@@ -191,6 +193,7 @@ static uint32_t action_display_lcd_off()
 #endif
     osDelay(100);        // Wait 100ms for the uikit to complete display.
     touch_screen_suspend(); // close touch
+    rotary_encoder_suspend();
     ext_errno ret = drv_vau_suspend(NULL);
     if (ret != 0) {
         POWER_DISPLAY_PRINT_ERR(0, "drv vau suspend error ret=%x\r\n", ret);
index 8a107be..ff6488d 100644 (file)
@@ -6,23 +6,37 @@ set(COMPONENT_NAME "rotary_encoder")
 
 if("ROTARYENCODER_HX3507" IN_LIST DEFINES)
 set(SOURCES
-    ${CMAKE_CURRENT_SOURCE_DIR}/hx3507.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/hx3507_at_cmd.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/hx3507/hx3507.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/hx3507/hx3507_hal.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/hx3507/hx3507_at_cmd.c
+)
+set(PUBLIC_HEADER
+    ${CMAKE_CURRENT_SOURCE_DIR}/hx3507
 )
 set(PUBLIC_DEFINES
 SUPPORT_AT_HX3507
 )
 else()
 set(SOURCES
-    ${CMAKE_CURRENT_SOURCE_DIR}/hx3507.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/hx3507_at_cmd.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/hx3507/hx3507.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/hx3507/hx3507_hal.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/hx3507/hx3507_at_cmd.c
+)
+set(PUBLIC_HEADER
+    ${CMAKE_CURRENT_SOURCE_DIR}/hx3507
 )
 set(PUBLIC_DEFINES
 SUPPORT_AT_HX3507
 )
 endif()
 
+set(SOURCES
+    ${SOURCES}
+    ${CMAKE_CURRENT_SOURCE_DIR}/rotary_encoder_drv.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/rotary_encoder_queue1.c
+)
 set(PUBLIC_HEADER
+    ${PUBLIC_HEADER}
     ${CMAKE_CURRENT_SOURCE_DIR}
 )
 
diff --git a/code/sdk/drivers/peripheral/rotary_encoder/hx3507/hx3507.c b/code/sdk/drivers/peripheral/rotary_encoder/hx3507/hx3507.c
new file mode 100644 (file)
index 0000000..74b1289
--- /dev/null
@@ -0,0 +1,542 @@
+/**
+ * Copyright (c) @CompanyNameMagicTag 2023-2023. All rights reserved. \n
+ *
+ * Description: Button driver source file \n
+ * Author: @CompanyNameTag \n
+ * History: \n
+ * 2023-02-24, Create file. \n
+ */
+
+#include "pinctrl.h"
+#include "button_porting.h"
+#include "platform_core.h"
+#include "gpio.h"
+#include "gpio_porting.h"
+#include "debug_print.h"
+#include "rtc.h"
+#include "timer.h"
+#include "systick.h"
+#include "chip_core_irq.h"
+#include "tcxo.h"
+#include "errcode.h"
+#include "pm_veto.h"
+
+/**
+ * Copyright (c) 2014 - 2023, 南京天易合芯电子有限公司
+ *
+ * All rights reserved.
+ *
+*/
+/*****************************************************************************
+    * @file     tyhx_crown_custom.c
+    * @author   Jiandang.Dong
+    * @date     2022-08-09 created
+    * @Emial    Jiandang.Dong@tianyihexin.com
+    * @brief    HX3507 驱动程序
+******************************************************************************/
+/*
+整体应用流程, 请见应用文档.
+先初始化IO, 执行crown_init 保证通信正确;
+在需要HX3507工作的时候, 调用crown_start(),  定时器启动,
+定时器周期处理调用crown_data_handler()来读取HX3507的数据;
+在HX3507 不需要工作的时候, 调用crown_stop() 让HX3507 进入power down状态
+*/
+
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "hx3507.h"
+
+// #ifdef CHIP_HX3507
+
+
+#include "cmsis_os2.h"
+
+osTimerId_t g_hx3507_timer = NULL;//定义一个定时器ID
+static uint8_t g_hx3695_timer_installed = 0;
+
+static int16_t crown_result = 0;
+
+/*----------------------以下为定时函数相关定义 建立/启动/停止定时器//定时中断处理-------------------------------*/
+
+
+
+/**
+ * 定时器超时处理函数
+ * @param p_context 是对应的定时器;
+ */
+void crown_timer_handler(void * p_context)
+{
+    UNUSED(p_context);
+    crown_data_handler(NULL,0);
+}
+/**
+ * 表冠定时器创建函数
+ * @param NULL
+ */
+void crown_timer_creat(void)
+{
+    if (g_hx3695_timer_installed == 1)
+     return ;
+    g_hx3507_timer = osTimerNew((osTimerFunc_t)crown_timer_handler, osTimerPeriodic, NULL, NULL);
+    g_hx3695_timer_installed = true;
+    return ;
+    // app_timer_create(&crown_timer_id, APP_TIMER_MODE_REPEATED, crown_timer_handler);
+}
+
+/**
+ * 定时器start函数 ,  目前定义的定时器是50ms, 用户可以根据需要改为100ms
+ * @param NULL
+ */
+void crown_timer_start(void)
+{
+     if(osTimerIsRunning(g_hx3507_timer)==0)
+        osTimerStart(g_hx3507_timer, 50);
+}
+
+/**
+ * 定时器stop函数
+ * @param timerid 是对应的定时器;
+ */
+void crown_timer_stop(void)
+{
+    if(osTimerIsRunning(g_hx3507_timer))
+        osTimerStop(g_hx3507_timer);
+}
+
+
+
+/*----------------------以上为定时函数相关定义 建立/启动/停止定时器//定时中断处理-------------------------------*/
+
+
+/*---------------------------以下为表冠的寄存器读写,初始化/开始/结束------------------------*/
+
+/**
+ * 通信重新同步函数, 作用是防止因为其他干扰而引起的错乱
+ * @param NULL;
+ */
+void crown_com_resync(void)
+{
+    uapi_gpio_set_val(PIN_TYHX_SCLK,GPIO_LEVEL_HIGH);
+    uapi_tcxo_delay_us(5);
+    uapi_gpio_set_val(PIN_TYHX_SCLK,GPIO_LEVEL_LOW);
+    uapi_tcxo_delay_us(5);
+    uapi_gpio_set_val(PIN_TYHX_SCLK,GPIO_LEVEL_HIGH);
+    uapi_tcxo_delay_ms(5);
+}
+
+/**
+ * 通信读寄存器值函数
+ * @param regaddr, hx3507的寄存器地址
+ * uapi_tcxo_delay_us(COM_DELAY), 读写函数的delay 按照实际平台调整, HX3507 通信sclk 最高支持1MHZ频率.
+ * 在最高频率的范围内, 尽量减小delay, 减少定时器周期读取的时间.
+ */
+uint8_t crown_read_reg(uint8_t regaddr)
+{
+    uint8_t readvalue = 0;
+
+    regaddr &= 0x7f;
+    uapi_gpio_set_val(PIN_TYHX_SDIO,GPIO_LEVEL_LOW);
+    uapi_gpio_set_val(PIN_TYHX_SCLK,GPIO_LEVEL_LOW);
+    uapi_tcxo_delay_us(COM_DELAY);
+
+    for(int i=0; i<8; i++)
+    {
+        uapi_gpio_set_val(PIN_TYHX_SCLK,GPIO_LEVEL_LOW);
+   
+        if(regaddr & 0x80)
+        {
+            uapi_gpio_set_val(PIN_TYHX_SDIO,GPIO_LEVEL_HIGH);
+        }
+        else
+        {
+            uapi_gpio_set_val(PIN_TYHX_SDIO,GPIO_LEVEL_LOW);
+   
+        }
+        //uapi_tcxo_delay_us(COM_DELAY);
+        uapi_gpio_set_val(PIN_TYHX_SCLK,GPIO_LEVEL_HIGH);
+        
+        regaddr<<=1;
+        //uapi_tcxo_delay_us(COM_DELAY);
+    }
+
+    //开始读操作,HOST要把SDIO从输出端口改为输入端口.
+    uapi_gpio_set_dir(PIN_TYHX_SDIO,GPIO_DIRECTION_INPUT);
+    uapi_pin_set_pull(PIN_TYHX_SDIO, (pin_pull_t)HAL_PIO_PULL_UP);
+    uapi_pin_set_ie(PIN_TYHX_SDIO,HAL_PIO_IE_ENBALE);
+    uapi_tcxo_delay_us(COM_DELAY);
+    //nrf_gpio_pin_clear(PIN_TYHX_SCLK);
+    //uapi_tcxo_delay_us(COM_DELAY);
+
+    for(int i=0; i<8; i++)
+    {
+        readvalue<<=1;
+        uapi_gpio_set_val(PIN_TYHX_SCLK,GPIO_LEVEL_LOW);
+   
+        //uapi_tcxo_delay_us(COM_DELAY);
+        uapi_gpio_set_val(PIN_TYHX_SCLK,GPIO_LEVEL_HIGH);
+        //uapi_tcxo_delay_us(COM_DELAY);
+        if(uapi_gpio_get_val(PIN_TYHX_SDIO))
+        {
+            readvalue |= 0x1;
+        }
+        //uapi_tcxo_delay_us(COM_DELAY);
+    }
+    uapi_gpio_set_dir(PIN_TYHX_SDIO,GPIO_DIRECTION_OUTPUT);
+    uapi_gpio_set_val(PIN_TYHX_SDIO,GPIO_LEVEL_LOW);
+    uapi_gpio_set_val(PIN_TYHX_SCLK,GPIO_LEVEL_LOW);
+   
+    return readvalue;
+}
+
+/**
+ * 通信读寄存器值函数
+ * @param regaddr, hx3507的寄存器地址
+ * @param regvalue, 要写的值
+ */
+void crown_write_reg(uint8_t regaddr, uint8_t regvalue)
+{
+
+    uint16_t writevalue;
+    uapi_gpio_set_val(PIN_TYHX_SDIO,GPIO_LEVEL_LOW);
+    uapi_gpio_set_val(PIN_TYHX_SCLK,GPIO_LEVEL_LOW);
+    uapi_tcxo_delay_us(COM_DELAY);
+
+    //写通信协议, 最高位置1, 循环16次依次送出寄存器和值,在SCLK的上升沿前准备好数据
+    writevalue= (uint16_t)((regaddr|0x80)<<8) + regvalue;
+
+    for(int i=0; i<16; i++)
+    {
+        uapi_gpio_set_val(PIN_TYHX_SCLK,GPIO_LEVEL_LOW);
+   
+        if(writevalue & 0x8000)
+        {
+            uapi_gpio_set_val(PIN_TYHX_SDIO,GPIO_LEVEL_HIGH);
+        }
+        else
+        {
+            uapi_gpio_set_val(PIN_TYHX_SDIO,GPIO_LEVEL_LOW);
+   
+        }
+        //uapi_tcxo_delay_us(COM_DELAY);
+        uapi_gpio_set_val(PIN_TYHX_SCLK,GPIO_LEVEL_HIGH);
+        
+        writevalue<<=1;
+    }
+    uapi_gpio_set_val(PIN_TYHX_SDIO,GPIO_LEVEL_LOW);
+    uapi_gpio_set_val(PIN_TYHX_SCLK,GPIO_LEVEL_LOW);
+   
+    return;
+}
+
+
+/**
+ * 某些OTS冠轴质量非常差, 这个是防呆处理
+ * @param xdata, 当前读到的OTS的有效轴的数据
+ * @result = true, 值有效, = false 这个值无效
+ */
+static bool crown_data_verify(int16_t xdata)
+{
+    static int16_t xstore[3] = {0};
+    uint16_t diff1, diff2, diff3= 0;
+
+    if(abs(xdata)>=600)//间隔50ms的一次读数
+    {
+        crown_timer_stop();
+        crown_start();
+        return false;
+    }
+    diff1 = abs(xstore[2]-xstore[1]);
+    diff2 = abs(xstore[1]-xstore[0]);
+    diff3 = abs(xstore[0]-xdata);
+
+    if((diff1<5) &&(diff2<=5) &&(diff3<=5) &&(abs(xdata)>=100))//连续四次读到接近的值
+    {
+        crown_timer_stop();
+        crown_start();
+        return false;
+    }
+    xstore[2] = xstore[1];
+    xstore[1] = xstore[0];
+    xstore[0] = xdata;
+    return true;
+}
+
+/**
+ * 周期定时器数据读取
+ * @param p_event_data, 参数暂时无用
+ * @param event_size, 参数暂时无用
+ */
+void crown_data_handler(void *p_event_data, uint16_t event_size)
+{
+    int16_t delatx = 0;
+    uint8_t sleepstatus = 0;
+    for(int i=0; i<5; i++)//先读一下芯片ID保证通信正常
+    {
+        if(crown_read_reg(HX3507_DID) == 0x30)
+        {
+            break;
+        }
+        else
+        {
+            crown_com_resync();
+        }
+    }
+    if(crown_read_reg(Motion_St)&0x80)
+    {
+#if defined(MOT_LOW_LEVEL_MODE) 
+        //如果有使用中断, 需要读取Y的值,          值读完, 中断电平才能恢复
+        int16_t delaty = 0;
+        delaty = crown_read_reg(DeltaY) |(crown_read_reg(DeltaY_Hi)<<8);
+#endif
+        //HX3507 一个方向转动出正值, 另外一个方向就是负值, 正负值跟芯片的摆放方向有关
+        delatx = crown_read_reg(DeltaX) |(crown_read_reg(DeltaX_Hi)<<8);
+        if(crown_data_verify(delatx)) //先判断数据是否合理, 
+        // 主要针对OTS冠轴质量,或者装配摆动幅度大引起的错误, 做的保护程序
+        {
+            //打印读取结果
+            TYHX_LOG("DeltaX = %d\r\n",delatx);
+            //把结果转换为大概的估算角度
+            put_crown_result(delatx);
+        }
+    }
+    else //下面这两个参数在产测程序里面需要加上
+    {
+        //冠轴静止的时候, 打印图像的质量和PD的饱和度, 这两个参数读取要放在出货测试的程序里面,
+        // 图像质量应该>=80, 否则可能代表芯片表面有脏污等或者装配问题或者有漏光
+        // PD的饱和度应该>=100 且 <=180, 如果有漏光等问题, 结果>=240以上, 相关漏光等要处理
+        // TYHX_LOG("pic qulity =%d, pd saturation=%d\r\n",crown_read_reg(Img_Qa),crown_read_reg(PD_SAT));
+    }
+
+#if (defined(MOT_LOW_LEVEL_MODE))//如果低电平中断模式,要读到芯片MOT变高
+    if(uapi_gpio_get_val(PIN_TYHX_MOT))
+    {
+        TYHX_LOG("PIN_TYHX_MOT is high \r\n");
+        crown_timer_stop();
+    }
+#endif
+
+#if (defined(MOT_FALLINGTRI_MODE))//如果是脉冲中断模式,要读到芯片进入sleep
+    sleepstatus = crown_read_reg(Op_St);
+    if((sleepstatus & 0x7) == 6)
+    {
+        TYHX_LOG("crown is sleep \r\n");
+        crown_timer_stop();
+    }
+#endif
+#if (defined(MOT_NO_USE_MODE))
+    //如果是MOT_NO_USE_MODE , 一般在屏幕熄掉,不需要HX3507工作的时候, 关闭定时器
+#endif
+
+}
+
+//MOT 中断处理程序,  这个是根据平台程序处理, 用户可以自行修改
+//这里加中断发生标志位或者把中断处理推送到其他任务队列, 因为中断函数里面不能加太多程序
+//下面的例子用的是NORDIC标准的程序,中断发生后GPIO的一个处理,并且把中断处理推送到任务队列
+#if (defined(MOT_LOW_LEVEL_MODE) || defined(MOT_FALLINGTRI_MODE))
+static void crown_int_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
+{
+    uint32_t err_code;
+    bool mothitolow = false;
+
+    nrf_drv_gpiote_in_uninit(PIN_TYHX_MOT);
+    if (action == NRF_GPIOTE_POLARITY_HITOLO)
+    {
+        mothitolow = true;
+        nrf_drv_gpiote_in_config_t config_crown = GPIOTE_CONFIG_IN_SENSE_LOTOHI(false);
+        err_code = nrf_drv_gpiote_in_init(PIN_TYHX_MOT, &config_crown, crown_int_handler);
+        APP_ERROR_CHECK(err_code);
+        config_crown.pull = NRF_GPIO_PIN_PULLUP;
+        nrf_drv_gpiote_in_event_enable(PIN_TYHX_MOT, true);
+    }
+    else
+    {
+        mothitolow = false;
+        nrf_drv_gpiote_in_config_t config_crown = GPIOTE_CONFIG_IN_SENSE_HITOLO(false);
+        err_code = nrf_drv_gpiote_in_init(PIN_TYHX_MOT, &config_crown, crown_int_handler);
+        APP_ERROR_CHECK(err_code);
+        config_crown.pull = NRF_GPIO_PIN_PULLUP;
+        nrf_drv_gpiote_in_event_enable(PIN_TYHX_MOT, true);
+    }
+    nrf_gpio_pin_latch_clear(PIN_TYHX_MOT);
+    if(mothitolow)
+    {
+        TYHX_LOG("mot interrupt! \r\n");
+        mothitolow = false;
+        crown_timer_start();
+    }
+
+}
+
+#endif
+
+
+/**
+ * HX3507 初始化
+ * @param NULL
+ */
+void crown_init(void)
+{
+    int i;
+    uapi_gpio_set_dir(PIN_TYHX_SDIO,GPIO_DIRECTION_INPUT);
+    uapi_gpio_set_dir(PIN_TYHX_SCLK,GPIO_DIRECTION_OUTPUT);
+    uapi_gpio_set_val(PIN_TYHX_SDIO,GPIO_LEVEL_LOW);
+    uapi_gpio_set_val(PIN_TYHX_SCLK,GPIO_LEVEL_LOW);
+   
+    uapi_tcxo_delay_us(COM_DELAY);
+    crown_com_resync();
+    for(i=0; i<10; i++)
+    {
+        if(crown_read_reg(HX3507_DID) == 0x30)
+        {
+            TYHX_LOG("read chip id is 0x30\r\n",i);
+            break;
+        }
+        if(i<7)//读到ID不对, 复位通信
+        {
+            crown_com_resync();
+        }
+    }
+    if(i==10)
+    {
+        TYHX_LOG("HX3507 communication err,  please check\r\n");
+        return;
+    }
+
+#if (defined(MOT_LOW_LEVEL_MODE) || defined(MOT_FALLINGTRI_MODE))
+    //中断定义
+    nrf_drv_gpiote_in_config_t config_crown = GPIOTE_CONFIG_IN_SENSE_HITOLO(false);
+    config_crown.pull = NRF_GPIO_PIN_PULLUP;
+    nrf_drv_gpiote_in_init(PIN_TYHX_MOT, &config_crown, crown_int_handler);
+    nrf_drv_gpiote_in_event_enable(PIN_TYHX_MOT, true);
+
+#endif
+    //定时器创建
+    crown_timer_creat();
+}
+
+
+/**
+ * HX3507 启动
+ * @param NULL
+ */
+void crown_start(void)
+{
+    int i = 0;
+    for(int i=0; i<5; i++)
+    {
+        crown_write_reg(Config_St,0x89); //RESET
+        uapi_tcxo_delay_ms(10);
+        TYHX_LOG("Reset ic, now init ---\r\n");
+
+#if defined(MOT_LOW_LEVEL_MODE)
+        crown_write_reg(Config_St,0x01);     //正常工作, MOT低电平中断
+        crown_write_reg(Op_Mode,0xb8);          //打开Sleep1 和 sleep2 功能
+        crown_write_reg(Sleep1_Setting,0xc0);
+        crown_write_reg(Enter_Time,0xc1);
+        crown_write_reg(Sleep2_Setting,0xc0);
+#elif defined(MOT_FALLINGTRI_MODE)
+        crown_write_reg(Config_St,0x41);     //正常工作, MOT下降沿中断
+        crown_write_reg(Op_Mode,0xb8);          //打开Sleep1 和 sleep2 功能
+        crown_write_reg(Sleep1_Setting,0xc0);
+        crown_write_reg(Enter_Time,0xc1);
+        crown_write_reg(Sleep2_Setting,0xc0);
+
+#elif defined(MOT_NO_USE_MODE)
+        crown_write_reg(Op_Mode,0xa0);           //关闭sleep功能
+#endif
+        crown_write_reg(Write_Protect,0xc3);   //enable all registers
+        crown_write_reg(Sleep1_Setting,0xc0);  //0x70,32ms.loop = 40ms. return 0 slowly
+        crown_write_reg(Enter_Time,0x0);       //sleep1=128*(Enter_Time[7:4]+1) sleep2=20480*(Enter_Time[3:0]+1)
+        crown_write_reg(DxDy_16bit,0x01);      //0:8bit,1:16bit
+        crown_write_reg(CPI2_Setting,0x88);    //800 cpi
+        crown_write_reg(HX3507_REV,0x00);
+        if(1 == crown_read_reg(DxDy_16bit) )
+        {
+            break;
+        }
+        else
+        {
+            crown_com_resync();
+        }
+    }
+    if(i==5)
+    {
+        TYHX_LOG("HX3507 init err,  please check\r\n");
+        return;
+    }
+
+
+#if 0  //这里非常关键, 在调试初期, 需要用#if 1 来验证寄存器写入的值和读出来的值是一样的, 通信正确
+    TYHX_LOG("Op_Mode = 0x%x\r\n",crown_read_reg(Op_Mode));
+    TYHX_LOG("Sleep1_Setting = 0x%x\r\n",crown_read_reg(Sleep1_Setting));
+    TYHX_LOG("DxDy_16bit = 0x%x\r\n",crown_read_reg(DxDy_16bit));
+    TYHX_LOG("CPI2_Setting = 0x%x\r\n",crown_read_reg(CPI2_Setting));
+#endif
+
+#ifdef MOT_NO_USE_MODE   // 如果是非中断模式, 初始后, 开启定时器; 
+    crown_timer_start();
+#endif
+
+
+
+}
+
+
+/**
+ * HX3507 停止
+ * @param NULL
+ */
+void crown_stop(void)
+{
+#ifdef MOT_NO_USE_MODE
+    crown_timer_stop();
+    crown_write_reg(Config_St,0x89); // power down, power down 后芯片功耗9uA
+    uapi_tcxo_delay_ms(20);
+    TYHX_LOG("[tyhx_crown_stop]\r\n");
+#endif
+}
+
+
+/**
+ * HX3507 结果转换为角度, 供UI处理
+ * @param NULL
+ */
+void put_crown_result(int16_t x)
+{
+    if(abs(x)<=FILTER_MIN )
+        return;
+    if(abs(x)>=4 )
+    {
+        crown_result += x/4; //大于4的值除以4, 代表角度, 单位0.5°
+    }
+    else
+    {
+        if(x>0)
+        {
+            crown_result+=1; //2~4 默认一个单位, 0.5°
+        }
+        else
+        {
+            crown_result-=1; //2~4 默认一个单位, 0.5°
+        }
+    }
+}
+
+/**
+ * 获取表冠的数据结果接口函数
+ * @param NULL
+*/
+int16_t get_crown_result(void)
+{
+    int16_t resulttemp;
+    resulttemp=crown_result;
+    crown_result = 0;
+    return resulttemp;
+}
+
+// #endif
+
diff --git a/code/sdk/drivers/peripheral/rotary_encoder/hx3507/hx3507.h b/code/sdk/drivers/peripheral/rotary_encoder/hx3507/hx3507.h
new file mode 100644 (file)
index 0000000..647601e
--- /dev/null
@@ -0,0 +1,91 @@
+/**
+ * Copyright (c) 2014 - 2023, 南京天易合芯电子有限公司
+ *
+ * All rights reserved.
+ *
+*/
+
+/***************************************************************************
+    * @file     TYHX_CROWN_CUSTOM.h
+    * @author   TYHX team
+       * @product  CROWN
+    * @version  V0.1
+    * @date     2022-08-09
+    * @modify date     2023-02-17
+
+****************************************************************************/
+#ifndef _TYHX_CROWN_CUSTOM_H_
+#define _TYHX_CROWN_CUSTOM_H_
+
+#include "debug_print.h"
+#define CHIP_HX3507  
+
+
+//三种中断模式的应用具体见“天易合芯表冠产品应用文档.docx"的流程说明,用户也可以定义自己的流程模式
+//#define MOT_LOW_LEVEL_MODE   //MOT使用低电平中断
+//#define MOT_FALLINGTRI_MODE  //MOT 使用低脉冲中断
+#define MOT_NO_USE_MODE        //用户不使用MOT 中断, 这个为常用的推荐模式
+
+
+//register define , addr, rw, default value, detail
+#define HX3507_DID      0x00  //R 0x30 芯片ID
+#define Motion_St       0x02  //R 是否有冠轴转动数据产生
+#define DeltaX          0x03  //R 0x30 DeltaX 的低8位数据
+#define DeltaY          0x04  //R 0x30 DeltaY 的低8位数据
+#define Op_Mode         0x05  //W/R  操作模式
+#define Config_St       0x06  //W/R  0x02 閰嶇疆
+#define Img_Qa          0x07  //R 图像质量
+#define Op_St           0x08  //R Sleep 和帧率设置
+#define Write_Protect   0x09  //W扩展寄存器的写使能
+#define Sleep1_Setting  0x0A  //W/R Sleep1 的工作频率设置
+#define Enter_Time      0x0B  //W/R  进入SLEEP的等待时间设置
+#define Sleep2_Setting  0x0C  // W/R  Sleep2的工作频率设置
+#define DeltaX_Hi       0x20  //R DeltaX 的高8位数据
+#define DeltaY_Hi       0x21  //R DeltaY的高8位数据
+#define DxDy_16bit      0x22  //数据输出寄存器选择16bit还是8bit格式
+#define CPI2_Setting    0x23  //W/R 扩展CPI 设置
+#define PD_SAT          0x3D  //PD 感光的饱和度
+#define HX3507_REV      0x5F  //W 保留寄存器
+
+#define COM_DELAY       5     // 通信的delay 单位, 用户根据平台实际调整, 最高支持1MHZ CLK
+#define FILTER_MIN      1     // 偶尔冠轴被震动等各种意外产生的小的数据,  可根据产品情况把小的出值滤掉
+
+//log 打印定义
+#define TYHX_LOG_ENABLE         
+#ifdef TYHX_LOG_ENABLE
+#define  TYHX_LOG(fmt, ...)                    \
+    do {                                      \
+        PRINT(fmt" ", ##__VA_ARGS__);     \
+    } while (0)
+#else 
+#define  TYHX_LOG(...)
+#endif //TYHX_LOG_ENABLE 
+
+
+/*----------------------使用的IO定义-------------------------------*/
+
+#define PIN_TYHX_SDIO      S_AGPIO_L12  //custom to do here
+#define PIN_TYHX_SCLK      S_AGPIO_L13  //custom to do here 
+#define PIN_TYHX_MOT       S_AGPIO_L17  //custom to do here 
+
+//定时器的 创建/启动/停止/溢出处理函数
+void crown_timer_creat(void);
+void crown_timer_start(void);
+void crown_timer_stop(void);
+void crown_timer_handler(void * p_context);
+
+//HX3507 初始化,启动,停止, 数据读取, 读寄存器, 写寄存器等, 通信同步
+void crown_init(void);
+void crown_start(void);
+void crown_stop(void);
+void crown_data_handler(void *p_event_data, uint16_t event_size);
+uint8_t crown_read_reg(uint8_t regaddr);
+void  crown_write_reg(uint8_t regaddr, uint8_t regvalue);
+void crown_com_resync(void);
+
+//把读出的数据转换为大概角度函数
+void put_crown_result(int16_t x);
+
+//把角度结果上报的函数
+int16_t get_crown_result(void);
+#endif //_TYHX_CROWN_CUSTOM_H_
diff --git a/code/sdk/drivers/peripheral/rotary_encoder/hx3507/hx3507_at_cmd.c b/code/sdk/drivers/peripheral/rotary_encoder/hx3507/hx3507_at_cmd.c
new file mode 100644 (file)
index 0000000..064256e
--- /dev/null
@@ -0,0 +1,92 @@
+
+// #include "hx3507.h"
+
+
+#include "at_cmd_api.h"
+#include "pm_control.h"
+#include "hx3507.h"
+
+#define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0]))
+#define HX3507_MAX_ARGC            8
+#define HX3507_MAX_ARGV_LEN        64
+
+#define HX3507_SUCCESS             0
+#define HX3507_FAILED              (-1)
+
+static int ConvertCmdToParam(uint8_t *para, uint32_t paraLen,
+        uint8_t argv[HX3507_MAX_ARGC][HX3507_MAX_ARGV_LEN], uint32_t* argc)
+{
+    uint32_t pos = 0;
+    *argc = 0;
+
+    for (uint32_t i = 0; i < paraLen; i++) {
+        if ((para[i] == ' ' || para[i] == '\n') && pos != 0) {
+            argv[*argc][pos] = '\0';
+            *argc += 1;
+            pos = 0;
+            if (*argc >= HX3507_MAX_ARGC) {
+                return HX3507_FAILED;
+            }
+        } else {
+            argv[*argc][pos] = para[i];
+            pos++;
+            if (pos >= HX3507_MAX_ARGV_LEN) {
+                return HX3507_FAILED;
+            }
+        }
+    }
+    if (pos != 0) {
+        *argc += 1;
+    }
+
+    return HX3507_SUCCESS;
+}
+
+static uint8_t g_hx3507_test_started = 0;
+static uint32_t hx3507_test(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    UNUSED(strCommonCmd);
+    uint8_t argv[HX3507_MAX_ARGC][HX3507_MAX_ARGV_LEN] = { 0 };
+    uint32_t argc = 0;
+
+    int ret = ConvertCmdToParam(para, paraLen, argv, &argc);
+    if (ret != HX3507_SUCCESS) {
+        PRINT("HX3507TEST ATCMD Convert Command Failed\n");
+        return ERRCODE_FAIL;
+    }
+
+    if (argc != 1) {
+        PRINT("HX3507TEST ATCMD Set Parameter Failed argc %d\n",argc);
+        return ERRCODE_FAIL;
+    }
+    uint8_t start = (uint8_t)atoi((char*)argv[0]);
+    if (start == 1)
+    {
+        if (g_hx3507_test_started == 1) 
+        {
+            PRINT("SKIP hx3507test start, already started\r\n");
+            return 0;
+        }
+        crown_init();
+        crown_start();
+        g_hx3507_test_started = 1;
+    }else{
+        if (g_hx3507_test_started == 0) 
+        {
+            PRINT("SKIP hx3507test stop, already stopped\r\n");
+            return 0;
+        }
+        crown_stop();
+        g_hx3507_test_started = 0 ;
+    }
+    return ERRCODE_SUCC;
+}
+static const at_cmd_table_t g_hx3507_cmd[] = {
+    { (char *)"AT^HX3507TEST",      hx3507_test, (char *)"1" },
+};
+
+at_cmd_table_t *get_hx3507_cmd_table(uint32_t *cmd_count)
+{
+    *cmd_count = ARRAY_COUNT(g_hx3507_cmd);
+    return (at_cmd_table_t *)g_hx3507_cmd;
+}
diff --git a/code/sdk/drivers/peripheral/rotary_encoder/hx3507/hx3507_at_cmd.h b/code/sdk/drivers/peripheral/rotary_encoder/hx3507/hx3507_at_cmd.h
new file mode 100644 (file)
index 0000000..cb7de85
--- /dev/null
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) @CompanyNameMagicTag 2022-2022. All rights reserved. \n
+ *
+ * Description: Provides at cmd register func \n
+ * Author: @CompanyNameTag \n
+ * History: \n
+ * 2022-07-20, Create file. \n
+ */
+#ifndef HX3507_AT_PROCESS_H
+#define HX3507_AT_PROCESS_H
+
+#include <stdint.h>
+#include <stdio.h>
+#include "errcode.h"
+#include "soc_osal.h"
+#include "at_cmd_api.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+at_cmd_table_t *get_mmc5603_cmd_table(uint32_t *cmd_count);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
diff --git a/code/sdk/drivers/peripheral/rotary_encoder/hx3507/hx3507_hal.c b/code/sdk/drivers/peripheral/rotary_encoder/hx3507/hx3507_hal.c
new file mode 100644 (file)
index 0000000..670426e
--- /dev/null
@@ -0,0 +1,132 @@
+
+// #include "hx3507.h"
+
+
+#include "at_cmd_api.h"
+#include "pm_control.h"
+#include "hx3507.h"
+#include "hx3507_hal.h"
+
+#include "rotary_encoder_def.h"
+#include "i2c.h"
+#include "debug_print.h"
+#include "hal_i2c.h"
+
+static uint8_t g_hx3507_test_started = 0;
+uint32_t hx3507_start(void)
+{
+    if (g_hx3507_test_started == 1) 
+    {
+        re_print("SKIP hx3507test start, already started\r\n");
+        return 0;
+    }
+    crown_init();
+    crown_start();
+    g_hx3507_test_started = 1;
+    return ERRCODE_SUCC;
+}
+uint32_t hx3507_stop(void)
+{
+    if (g_hx3507_test_started == 0) 
+    {
+        re_print("SKIP hx3507test stop, already stopped\r\n");
+        return 0;
+    }
+    crown_stop();
+    g_hx3507_test_started = 0 ;
+    return ERRCODE_SUCC;
+}
+
+static ext_errno hx3507_encoder_init(void *attr)
+{
+    re_print("hx3507_encoder_init\r\n");
+    return EXT_ERR_SUCCESS;
+}
+static ext_errno hx3507_encoder_deinit(void)
+{
+    re_print("hx3507_encoder_deinit\r\n");
+    return EXT_ERR_SUCCESS;
+}
+static ext_errno hx3507_encoder_get_encoderinfo(uint8_t *data, uint8_t data_len)
+{
+
+    re_print("hx3507_encoder_get_encoderinfo\r\n");
+    if (data_len != sizeof(re_input_event_info))
+        return EXT_ERR_NOT_SUPPORT;
+    re_input_event_info *encoder_info = (re_input_event_info*)data;
+    int16_t diff = get_crown_result();
+    if (diff > 0 )
+    {
+        encoder_info->re_event = MC_RE_SLIDE_UP;
+    }else{
+        encoder_info->re_event = MC_RE_SLIDE_DOWN;
+    }
+    encoder_info->re_event_info.x_axis[0] = diff;
+    encoder_info->re_event_info.y_axis[0] = diff;
+    encoder_info->re_event_info.z_axis[0] = diff;
+    encoder_info->finger_id = 0 ;
+    encoder_info->point_num = 0 ;
+    encoder_info->tv_usec = (uint32_t)uapi_tcxo_get_ms();
+
+    return EXT_ERR_SUCCESS;
+}
+static ext_errno hx3507_encoder_suspend(void)
+{
+    re_print("hx3507_encoder_suspend\r\n");
+    return EXT_ERR_SUCCESS;
+}
+static ext_errno hx3507_encoder_resume(void)
+{
+    re_print("hx3507_encoder_resume\r\n");
+    hx3507_start();
+    return EXT_ERR_SUCCESS;
+}
+static ext_errno hx3507_encoder_sleep(void)
+{
+    re_print("hx3507_encoder_sleep\r\n");
+    hx3507_stop();
+    return EXT_ERR_SUCCESS;
+}
+static ext_errno hx3507_encoder_reset(void)
+{
+    re_print("hx3507_encoder_reset\r\n");
+    return EXT_ERR_SUCCESS;
+}
+static ext_errno hx3507_encoder_bus_init(void *private_data)
+{
+    return EXT_ERR_SUCCESS;
+}
+static ext_errno hx3507_register_callback(void *peri_data, encoder_callback func)
+{
+    re_print("hx3507_register_callback\r\n");
+    return EXT_ERR_SUCCESS;
+}
+static ext_errno hx3507_unregister_callback(void *peri_data)
+{
+    re_print("hx3507_unregister_callback\r\n");
+    return EXT_ERR_SUCCESS;
+}
+
+encoder_peripheral_api g_hx3507_api = {
+    .encoder_init = hx3507_encoder_init,
+    .encoder_deinit = hx3507_encoder_deinit,
+    .encoder_get_encoderinfo = hx3507_encoder_get_encoderinfo,
+    .encoder_suspend = hx3507_encoder_suspend,
+    .encoder_resume = hx3507_encoder_resume,
+    .encoder_sleep = hx3507_encoder_sleep,
+    .encoder_reset = hx3507_encoder_reset,
+    .encoder_bus_init = hx3507_encoder_bus_init,
+    .register_callback = hx3507_register_callback,
+    .unregister_callback = hx3507_unregister_callback,
+};
+
+
+void *rotary_encoder_get_api(void)
+{
+    return ((void *)&g_hx3507_api);
+}
+
+void *rotary_encoder_get_peri_attr(void)
+{
+    return ((void *)NULL);
+}
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/rotary_encoder/hx3507/hx3507_hal.h b/code/sdk/drivers/peripheral/rotary_encoder/hx3507/hx3507_hal.h
new file mode 100644 (file)
index 0000000..74e2633
--- /dev/null
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) @CompanyNameMagicTag 2022-2022. All rights reserved. \n
+ *
+ * Description: Provides at cmd register func \n
+ * Author: @CompanyNameTag \n
+ * History: \n
+ * 2022-07-20, Create file. \n
+ */
+#ifndef HX3507_HAL_H
+#define HX3507_HAL_H
+
+#include <stdint.h>
+#include <stdio.h>
+#include "errcode.h"
+#include "soc_osal.h"
+#include "at_cmd_api.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+at_cmd_table_t *get_mmc5603_cmd_table(uint32_t *cmd_count);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
diff --git a/code/sdk/drivers/peripheral/rotary_encoder/rotary_encoder_def.h b/code/sdk/drivers/peripheral/rotary_encoder/rotary_encoder_def.h
new file mode 100644 (file)
index 0000000..773755e
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) @CompanyNameMagicTag 2021-2021. All rights reserved.
+ * Description: touch screen common definition.
+ * Author: @CompanyNameTag
+ * Create: 2022-04-12
+ */
+
+#ifndef ROTARY_ENCODER_DEF_H
+#define ROTARY_ENCODER_DEF_H
+
+#include "stdio.h"
+#include "soc_errno.h"
+#include "osal_ioctl.h"
+#include "input_manager.h"
+#include "debug_print.h"
+#if defined(SUPPORT_POWER_MANAGER)
+#include "power_display_service.h"
+#endif
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+#define RE_DEBUG 
+
+#define INPUT_TOUCH_MODULE_ID  0x61
+#define CMD_GET_TOUCH_INFO     0
+#define ROTARY_ENCODER_GET_EVENT _IOWR(INPUT_TOUCH_MODULE_ID, CMD_GET_TOUCH_INFO, re_input_event_info)
+
+/* common definitions */
+#define re_mem_free(sz)                   \
+    do {                                  \
+        if ((sz) != NULL) {            \
+            osal_kfree((sz));                \
+        }                                 \
+        (sz) = NULL;                   \
+    } while (0)
+
+#ifdef RE_DEBUG
+#define re_print(fmt, ...)                    \
+    do {                                      \
+        PRINT(fmt"\r\n", ##__VA_ARGS__);     \
+    } while (0)
+#else
+#define re_print(ftm, ...)
+#endif
+
+#define re_err(x, ...) \
+    do { \
+        PRINT("[ERROR]%s(%d): "x"\r\n", __FUNCTION__, __LINE__, ##__VA_ARGS__); \
+    } while (0)
+
+#define re_warning(x, ...) \
+    do { \
+        PRINT("[WARNING]%s(%d): "x"\r\n", __FUNCTION__, __LINE__, ##__VA_ARGS__); \
+    } while (0)
+
+
+
+typedef enum {
+    MC_RE_PRESS = 0,
+    MC_RE_RELEASE = 1,
+    MC_RE_MOVE = 2,
+    MC_RE_COVER = 3,
+    MC_RE_SHORT_CLICK = 4,
+    MC_RE_DOUBLE_CLICK = 5,
+    MC_RE_SLIDE_UP = 6,
+    MC_RE_SLIDE_DOWN = 7,
+    MC_RE_INVALID,
+} re_event_type;
+
+typedef struct {
+    uint32_t x_axis[1];
+    uint32_t y_axis[1];
+    uint32_t z_axis[1];
+} re_dev_info;
+
+typedef struct {
+    re_dev_info re_event_info;
+    re_event_type re_event;
+    uint32_t finger_id;
+    uint32_t point_num;
+    uint32_t tv_usec;
+} re_input_event_info;
+
+typedef void (*encoder_callback)(void);
+
+typedef struct {
+    ext_errno (*encoder_init)(void *attr);
+    ext_errno (*encoder_deinit)(void);
+    ext_errno (*encoder_get_encoderinfo)(uint8_t *data, uint8_t data_len);
+    ext_errno (*encoder_suspend)(void);
+    ext_errno (*encoder_resume)(void);
+    ext_errno (*encoder_sleep)(void);
+    ext_errno (*encoder_reset)(void);
+    ext_errno (*encoder_bus_init)(void *private_data);
+    ext_errno (*register_callback)(void *peri_data, encoder_callback func);
+    ext_errno (*unregister_callback)(void *peri_data);
+} encoder_peripheral_api;
+
+uint32_t re_register_report_event_cb(report_event_cb callback);
+uint32_t re_unregister_report_event_cb(void);
+uint32_t re_init(void);
+uint32_t re_close(void);
+uint32_t re_read(const input_dev_data_t* data);
+void rotary_encoder_suspend(void);
+void rotary_encoder_resume(void);
+void rotary_encoder_restart(void);
+void encoder_suspend_for_i2c(void);
+void encoder_resume_for_i2c(void);
+#if defined(SUPPORT_POWER_MANAGER)
+uint32_t re_register_power_manager_cb(event_callback_func callback);
+#endif
+
+#ifdef __cplusplus
+#if __cplusplus
+    }
+#endif
+#endif
+
+#endif
diff --git a/code/sdk/drivers/peripheral/rotary_encoder/rotary_encoder_drv.c b/code/sdk/drivers/peripheral/rotary_encoder/rotary_encoder_drv.c
new file mode 100644 (file)
index 0000000..f90f2c5
--- /dev/null
@@ -0,0 +1,447 @@
+/*
+ * Copyright (c) @CompanyNameMagicTag 2021-2021. All rights reserved.
+ * Description: rotary encoder driver.
+ * Author: @CompanyNameTag
+ * Create: 2022-04-12
+ */
+
+#include "rotary_encoder_drv.h"
+#include "tcxo.h"
+#include "i2c.h"
+#include "common_def.h"
+#include "soc_osal.h"
+#include "rotary_encoder_def.h"
+#include "input_app.h"
+#if defined(TPTYPE_TMA525B)
+#include "tma525b_drv1.h"
+#include "tma525b_ctrl.h"
+#elif defined(TPTYPE_ZTW523)
+#include "ztw523_drv1.h"
+#include "ztw523_ctrl.h"
+#elif defined(TPTYPE_FT6X46)
+#include "ft6x46_drv1.h"
+#include "ft6x46_ctrl.h"
+#else
+#include "ztw523_drv1.h"
+#include "ztw523_ctrl.h"
+#endif
+
+#define ROTARY_ENCODER_DEV_NAME_LEN 16
+#define ROTARY_ENCODER_DEVNAME "input/event"
+#define ROTARY_ENCODER_DYNAMIC_MINOR 65
+#define ROTARY_ENCODER_CMDID_MAX 16
+
+#define ROTARY_ENCODER_TASK_PRIO      5
+#define ROTARY_ENCODER_TASK_SIZE      0x800
+#define ROTARY_ENCODER_QUEUE_MAX_SIZE 60
+#define ROTARY_ENCODER_READY_EVENT    (1 << 0)
+
+struct re_driver_data g_encoder_drv = {0};
+struct re_driver_data *g_attr_re = NULL;
+
+report_event_cb g_re_report_event_cb = NULL;
+
+#if defined(SUPPORT_POWER_MANAGER)
+event_callback_func g_power_manager_re_cb = NULL;
+#endif
+
+static struct re_driver_data *rotary_encoder_get_driver_data(void)
+{
+    return &g_encoder_drv;
+}
+
+static uint32_t rotary_encoder_get_state(struct re_driver_data *redd)
+{
+    if (redd != NULL && redd->queue != NULL) {
+        return (uint32_t)re_queue_is_empty(redd->queue);
+    }
+
+    if (redd == NULL) {
+        re_err("redd is null!");
+        return EXT_ERR_FAILURE;
+    }
+    if (redd->queue == NULL) {
+        re_err("redd queue is null!");
+    }
+
+    return EXT_ERR_FAILURE;
+}
+
+static void convert_encoder_info(input_dev_data_t* data, re_input_event_info* encoder_info)
+{
+    data->x = (int16_t)encoder_info->re_event_info.x_axis[0];
+    data->y = (int16_t)encoder_info->re_event_info.y_axis[0];
+    data->type = INDEV_TYPE_TOUCH;
+    data->timestamp = (uint32_t)encoder_info->tv_usec;
+    if ((encoder_info->re_event == MC_RE_PRESS) || (encoder_info->re_event == MC_RE_MOVE)) {
+        data->state = INDEV_STATE_PRESS;
+    } else if (encoder_info->re_event == MC_RE_RELEASE) {
+        data->state = INDEV_STATE_RELEASE;
+    } else {
+        data->state = INDEV_STATE_UNKNOWN;
+    }
+}
+
+static void report_or_enqueue_event(re_input_event_info* encoder_info, struct re_driver_data *redd)
+{
+    if (g_re_report_event_cb != NULL) {
+        input_dev_data_t data;
+        convert_encoder_info(&data, encoder_info);
+        if (data.state == INDEV_STATE_UNKNOWN) {
+            return;
+        }
+        g_re_report_event_cb(&data);
+    } else {
+        int32_t ret = re_en_queue(redd->queue, encoder_info);
+        if (ret != EXT_ERR_SUCCESS) {
+            re_err("Failed to enqueue ts queue! ret=0x%x", ret);
+        }
+    }
+}
+#if defined(SUPPORT_POWER_MANAGER)
+static void report_event_to_power_manager(re_input_event_info *encoder_info)
+{
+    if (g_power_manager_re_cb != NULL) {
+        input_dev_data_t data;
+        convert_encoder_info(&data, encoder_info);
+        if (data.state == INDEV_STATE_UNKNOWN) {
+            return;
+        }
+        g_power_manager_re_cb(data.state, 0);
+    }
+    return;
+}
+
+uint32_t re_register_power_manager_cb(event_callback_func callback)
+{
+    if (g_power_manager_re_cb != NULL) {
+        return EXT_ERR_FAILURE;
+    }
+    g_power_manager_re_cb = callback;
+    return EXT_ERR_SUCCESS;
+}
+#endif
+ext_errno encoder_info_process(void)
+{
+    struct re_driver_data *redd = rotary_encoder_get_driver_data();
+    re_input_event_info encoder_info;
+    int32_t ret = 0;
+
+    if (redd->encoder_api->encoder_get_encoderinfo != NULL) {
+        ret = redd->encoder_api->encoder_get_encoderinfo((uint8_t *)(&encoder_info), sizeof(re_input_event_info));
+        if (ret != EXT_ERR_SUCCESS) {
+            re_err("get encoder info fail! ret=0x%x", ret);
+        }
+
+        report_or_enqueue_event(&encoder_info, redd);
+#if defined(SUPPORT_POWER_MANAGER)
+        report_event_to_power_manager(&encoder_info);
+#endif
+    }
+
+    return EXT_ERR_SUCCESS;
+}
+
+static void re_callback_func(void)
+{
+    ext_errno ret;
+    if (g_attr_re != NULL) {
+        common_notify_mail_t mail = {0};
+        mail.comm.app = APP_ENCODER;
+        ret = osal_msg_queue_write_copy(get_app_queue_id(), (void *)&mail,
+                                        sizeof(common_notify_mail_t), 0);
+        if (ret != OSAL_SUCCESS) {
+            re_err("encoder app msg send failed! err=0x%x! \r\n", ret);
+        }
+    }
+}
+
+static ext_errno re_register_callback(struct re_driver_data *attr)
+{
+    ext_errno ret = EXT_ERR_FAILURE;
+    g_attr_re = attr;
+
+    if (attr->encoder_api->register_callback != NULL) {
+        ret = attr->encoder_api->register_callback(attr->private_data, re_callback_func);
+        if (ret != EXT_ERR_SUCCESS) {
+            re_err("register rotary encoder callback fail! ret=0x%x", ret);
+            return ret;
+        }
+    } else {
+        re_err("rotary encoder callback register func is empty!");
+    }
+
+    return ret;
+}
+
+static ext_errno re_unregister_callback(struct re_driver_data *attr)
+{
+    ext_errno ret = EXT_ERR_FAILURE;
+
+    if (attr->encoder_api->unregister_callback != NULL) {
+        ret = attr->encoder_api->unregister_callback(attr->private_data);
+        if (ret != EXT_ERR_SUCCESS) {
+            re_err("unregister rotary encoder callback fail! ret=0x%x", ret);
+            return ret;
+        }
+        g_attr_re = NULL;
+    } else {
+        re_err("rotary encoder callback unregister func is empty!");
+    }
+
+    return ret;
+}
+
+static int32_t re_dev_open(const void *private_data)
+{
+    int32_t ret;
+    struct re_driver_data *redd = NULL;
+    if (private_data == NULL) {
+        re_err("re_open: invalid dev or driver_data!\n");
+        return EXT_ERR_FAILURE;
+    }
+
+    // todo: get redd from private_data
+    redd = rotary_encoder_get_driver_data();
+    redd->queue = re_init_queue(ROTARY_ENCODER_QUEUE_MAX_SIZE);
+    if (redd->queue == NULL) {
+        re_err("create rotary encoder queue fail!\r\n");
+        return EXT_ERR_FAILURE;
+    }
+    ret = osal_event_init(&(redd->event));
+    if (ret != EXT_ERR_SUCCESS) {
+        re_err("encoder osal_event_init fail! ret=0x%x\r\n", ret);
+        return ret;
+    }
+
+    redd->task_handle = osal_kthread_create((osal_kthread_handler)encoder_info_process,
+                                            (void *)rotary_encoder_get_driver_data(),
+                                            "rotary_encoder", ROTARY_ENCODER_TASK_SIZE);
+    if (redd->task_handle == NULL) {
+        re_err("create rotary encoder thread fail!\r\n");
+        return EXT_ERR_FAILURE;
+    }
+    osal_kthread_set_priority(redd->task_handle, ROTARY_ENCODER_TASK_PRIO);
+
+    if (redd->encoder_api->encoder_init != NULL) {
+        ret = redd->encoder_api->encoder_init(redd->private_data);
+        if (ret != EXT_ERR_SUCCESS) {
+            re_err("encoder_init fail! ret=0x%x\r\n", ret);
+            return ret;
+        }
+    }
+
+    ret = re_register_callback(redd);
+    if (ret != EXT_ERR_SUCCESS) {
+        re_err("register callback fail! ret=0x%x\r\n", ret);
+        return ret;
+    }
+
+    return EXT_ERR_SUCCESS;
+}
+
+static int32_t re_dev_release(const void *private_data)
+{
+    int32_t ret;
+    struct re_driver_data *redd = NULL;
+    if (private_data == NULL) {
+        re_err("re_dev_release: invalid dev or driver_data!\n");
+        return EXT_ERR_FAILURE;
+    }
+
+    // todo: get redd from private_data
+    redd = rotary_encoder_get_driver_data();
+    ret = re_unregister_callback(redd);
+    if (ret != EXT_ERR_SUCCESS) {
+        re_err("unregister callback fail! ret=0x%x\r\n", ret);
+        return ret;
+    }
+    return EXT_ERR_SUCCESS;
+}
+
+static uint32_t re_dev_poll(const osal_poll *osal_poll, const void *private_data)
+{
+    unused(osal_poll);
+    unused(private_data);
+    // todo: get redd from private_data
+    struct re_driver_data *redd = NULL;
+    redd = rotary_encoder_get_driver_data();
+    if (redd == NULL) {
+        re_err("re_driver_data is NULL");
+        return EXT_ERR_FAILURE;
+    }
+
+    if (redd->ops->priv_operator != NULL && redd->ops->priv_operator(redd) == 0) {
+        return OSAL_POLLIN | OSAL_POLLRDNORM;
+    }
+
+    return EXT_ERR_SUCCESS;
+}
+
+static int32_t re_ioctl_read_encoder_info(uint32_t cmd, void *arg, const void *private_data)
+{
+    unused(cmd);
+    ext_errno ret;
+    struct re_driver_data *redd = NULL;
+    re_input_event_info *encoder_info = (re_input_event_info *)arg;
+
+    if (private_data == NULL) {
+        re_err("invalid dev or driver_data!");
+        return EXT_ERR_FAILURE;
+    }
+
+    // todo: get redd from private_data
+    redd = rotary_encoder_get_driver_data();
+    if (redd->queue == NULL) {
+        re_err("invalid rotary encoder queue!");
+        return EXT_ERR_FAILURE;
+    }
+
+    ret = re_de_queue(redd->queue, encoder_info);
+    if (ret != EXT_ERR_SUCCESS) {
+        re_err("get encoder info fail! ret=0x%x", ret);
+        return ret;
+    }
+
+    return EXT_ERR_SUCCESS;
+}
+
+static osal_ioctl_cmd g_re_cmd_list[ROTARY_ENCODER_CMDID_MAX] = {
+    {ROTARY_ENCODER_GET_EVENT, re_ioctl_read_encoder_info},
+};
+
+static osal_dev *g_re_dev = NULL;
+static osal_fileops g_re_ops = {
+    .open = re_dev_open,
+    .release = re_dev_release,
+    .poll = re_dev_poll,
+    .cmd_list = g_re_cmd_list,
+    .cmd_cnt = sizeof(g_re_cmd_list) / sizeof(g_re_cmd_list[0]),
+};
+
+struct re_ops g_re_status_ops = {
+    .priv_operator  = rotary_encoder_get_state,
+};
+
+static ext_errno rotary_encoder_register_device(void)
+{
+    ext_errno ret;
+
+    g_encoder_drv.private_data = rotary_encoder_get_peri_attr();
+    g_encoder_drv.encoder_api = rotary_encoder_get_api();
+    g_encoder_drv.ops = &g_re_status_ops;
+    g_re_dev = osal_dev_create(ROTARY_ENCODER_DEVNAME);
+    g_re_dev->minor = ROTARY_ENCODER_DYNAMIC_MINOR;
+    g_re_dev->fops = &g_re_ops;
+
+    ret = osal_dev_register(g_re_dev);
+    if (ret != 0) {
+        re_err("rotary encoder osal_dev_register --------failed! ret=0x%x\n", ret);
+        return EXT_ERR_FAILURE;
+    }
+
+    return EXT_ERR_SUCCESS;
+}
+
+ext_errno rotary_encoder_module_init(void)
+{
+    ext_errno ret;
+
+    ret = rotary_encoder_register_device();
+    if (ret != EXT_ERR_SUCCESS) {
+        re_err("rotary_encoder_register_device ----------failed! ret=0x%x\n", ret);
+    }
+    re_err("rotary_encoder_register_device ----------succ!!!\n");
+
+    return EXT_ERR_SUCCESS;
+}
+
+ext_errno rotary_encoder_module_deinit(void)
+{
+    return EXT_ERR_SUCCESS;
+}
+
+uint32_t re_register_report_event_cb(report_event_cb callback)
+{
+    if (g_re_report_event_cb != NULL) {
+        return EXT_ERR_FAILURE;
+    }
+    g_re_report_event_cb = callback;
+    return EXT_ERR_SUCCESS;
+}
+
+uint32_t re_unregister_report_event_cb(void)
+{
+    g_re_report_event_cb = NULL;
+    return EXT_ERR_SUCCESS;
+}
+
+uint32_t re_init(void)
+{
+    int32_t ret;
+    struct re_driver_data *redd = NULL;
+
+    g_encoder_drv.private_data = rotary_encoder_get_peri_attr();
+    g_encoder_drv.encoder_api = rotary_encoder_get_api();
+    g_encoder_drv.ops = &g_re_status_ops;
+    redd = rotary_encoder_get_driver_data();
+    redd->queue = re_init_queue(ROTARY_ENCODER_QUEUE_MAX_SIZE);
+    if (redd->queue == NULL) {
+        re_err("create rotary encoder queue fail!\r\n");
+        return EXT_ERR_FAILURE;
+    }
+
+    ret = re_register_callback(redd);
+    if (ret != EXT_ERR_SUCCESS) {
+        re_err("register callback fail! ret=0x%x\r\n", ret);
+        return EXT_ERR_FAILURE;
+    }
+
+    return EXT_ERR_SUCCESS;
+}
+
+uint32_t re_read(const input_dev_data_t* data)
+{
+    unused(data);
+    return EXT_ERR_SUCCESS;
+}
+
+uint32_t re_close(void)
+{
+    return EXT_ERR_SUCCESS;
+}
+
+void rotary_encoder_suspend(void)
+{
+
+    /**灭屏,关闭Encoder*/
+    encoder_peripheral_api *encoder_ptr = rotary_encoder_get_api();
+    ext_errno ret = encoder_ptr->encoder_sleep();
+    if (ret != EXT_ERR_SUCCESS) { re_err("encoder sleep ret=0x%x", ret); }
+
+}
+
+void rotary_encoder_resume(void)
+{
+    /**亮屏,恢复Encoder工作*/
+    encoder_peripheral_api *encoder_ptr = (encoder_peripheral_api*)rotary_encoder_get_api();
+    ext_errno ret = encoder_ptr->encoder_resume();
+    if (ret != EXT_ERR_SUCCESS) { re_err("encoder resume ret=0x%x", ret); }
+}
+
+void encoder_suspend_for_i2c(void)
+{
+    // i2c_save_reg(TOUCH_I2C_BUS);
+}
+
+void encoder_resume_for_i2c(void)
+{
+    // i2c_recovery_reg(TOUCH_I2C_BUS);
+}
+
+void rotary_encoder_restart(void)
+{
+    // uapi_i2c_deinit(TOUCH_I2C_BUS);
+    // uapi_i2c_master_init(TOUCH_I2C_BUS, 400000, I2C_SPEED_MODE_FS); /* 400000: 400KHz */
+
+}
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/rotary_encoder/rotary_encoder_drv.h b/code/sdk/drivers/peripheral/rotary_encoder/rotary_encoder_drv.h
new file mode 100644 (file)
index 0000000..3a37a05
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) @CompanyNameMagicTag 2021-2022. All rights reserved.
+ * Description: header of touch screen driver.
+ * Author: @CompanyNameTag
+ * Create: 2022-04-12
+ */
+
+#ifndef ROTARY_ENCODER_DRV_H
+#define ROTARY_ENCODER_DRV_H
+
+#include "soc_osal.h"
+#include "rotary_encoder_queue1.h"
+
+struct re_driver_data {
+    osal_task *task_handle;
+    osal_event event;
+    re_queue_t *queue;
+    osal_wait wait;
+    struct re_ops *ops;
+    encoder_peripheral_api *encoder_api;
+    void *private_data;
+};
+
+struct re_ops {
+    /* private operation */
+    uint32_t (*priv_operator)(struct re_driver_data *udd);
+};
+
+ext_errno rotary_encoder_module_init(void);
+ext_errno rotary_encoder_module_deinit(void);
+ext_errno encoder_info_process(void);
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/rotary_encoder/rotary_encoder_queue1.c b/code/sdk/drivers/peripheral/rotary_encoder/rotary_encoder_queue1.c
new file mode 100644 (file)
index 0000000..4dc7296
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) @CompanyNameMagicTag 2021-2021. All rights reserved.
+ * Description: touch screen msg queue.
+ * Author: @CompanyNameTag
+ * Create: 2022-04-18
+ */
+
+#include "rotary_encoder_queue1.h"
+#include "securec.h"
+#include "soc_osal.h"
+#include "debug_print.h"
+
+#define re_queue_err(x, ...) \
+    do { \
+        PRINT("[ERROR]%s(%d): "x"\r\n", __FUNCTION__, __LINE__, ##__VA_ARGS__); \
+    } while (0)
+
+osal_mutex g_re_mutex;
+
+static ext_errno re_lock_init(void)
+{
+    ext_errno ret;
+    ret = osal_mutex_init(&(g_re_mutex));
+    if (ret != EXT_ERR_SUCCESS) {
+        g_re_mutex.mutex = NULL;
+        return ret;
+    }
+
+    return EXT_ERR_SUCCESS;
+}
+
+static void re_lock_deinit(void)
+{
+    osal_mutex_destroy(&(g_re_mutex));
+}
+
+static void re_lock(void)
+{
+    osal_mutex_lock(&(g_re_mutex));
+}
+
+static void re_unlock(void)
+{
+    osal_mutex_unlock(&(g_re_mutex));
+}
+
+re_queue_t *re_init_queue(uint32_t capacity)
+{
+    ext_errno ret;
+    re_queue_t *q = (re_queue_t *)osal_kmalloc(sizeof(re_queue_t), OSAL_GFP_KERNEL);
+    if (q == NULL) {
+        return NULL;
+    }
+    q->cap = capacity;
+    q->cnt = 0;
+    q->head = q->tail = NULL;
+
+    ret = re_lock_init();
+    if (ret != EXT_ERR_SUCCESS) {
+        re_mem_free(q);
+    }
+
+    return q;
+}
+
+int32_t re_queue_get_length(re_queue_t *q)
+{
+    return (int32_t)q->cnt;
+}
+
+int32_t re_queue_is_empty(const re_queue_t *q)
+{
+    return (q->cnt == 0);
+}
+
+int32_t re_queue_is_full(const re_queue_t *q)
+{
+    return (q->cnt == q->cap);
+}
+
+int32_t re_de_queue(re_queue_t *q, re_input_event_info *msg)
+{
+    if (q == NULL || q->head == NULL || msg == NULL || re_queue_is_empty(q) != 0) {
+        return -1;
+    }
+
+    re_lock();
+    struct re_list *node = q->head;
+    errno_t ret = memcpy_s(msg, sizeof(re_input_event_info), node->msg, sizeof(re_input_event_info));
+    if (ret != EOK) {
+        PRINT("de queue memcpy_s fail\r\n");
+    }
+    q->head = q->head->next;
+    q->cnt--;
+
+    re_mem_free(node->msg);
+    re_mem_free(node);
+    if (q->cnt == 0) {
+        q->tail = NULL;
+    }
+    re_unlock();
+
+    return 0;
+}
+
+int32_t re_en_queue(re_queue_t *q, re_input_event_info *msg)
+{
+    if (q == NULL || msg == NULL) {
+        return -1;
+    }
+    if (re_queue_is_full(q) != 0) {
+        re_input_event_info tmp_msg = {0};
+        re_de_queue(q, &tmp_msg);
+    }
+
+    struct re_list *node = osal_kmalloc(sizeof(struct re_list), OSAL_GFP_KERNEL);
+    if (node == NULL) {
+        return -1;
+    }
+    node->msg = (re_input_event_info *)osal_kmalloc(sizeof(re_input_event_info), OSAL_GFP_KERNEL);
+    if (node->msg == NULL) {
+        re_mem_free(node);
+        return -1;
+    }
+
+    errno_t ret = memcpy_s(node->msg, sizeof(re_input_event_info), msg, sizeof(re_input_event_info));
+    if (ret != EOK) {
+        PRINT("en queue memcpy_s fail\r\n");
+    }
+    node->next = NULL;
+
+    re_lock();
+    if (re_queue_is_empty(q) != 0) {
+        q->head = node;
+    } else {
+        q->tail->next = node;
+    }
+    q->tail = node;
+    q->cnt++;
+    re_unlock();
+
+    return 0;
+}
+
+void re_clear_queue(re_queue_t *q)
+{
+    re_lock();
+    if (q == NULL) {
+        re_unlock();
+        return;
+    }
+    struct re_list *curr = q->head;
+    struct re_list *next = curr->next;
+
+    while (curr != NULL) {
+        re_mem_free(curr->msg);
+        re_mem_free(curr);
+        curr = next;
+        if (next != NULL) {
+            next = next->next;
+        }
+    }
+    q->cnt = 0;
+    re_unlock();
+}
+
+void re_delete_queue(re_queue_t *q)
+{
+    re_lock();
+    if (q == NULL) {
+        re_unlock();
+        return;
+    }
+    struct re_list *curr = q->head;
+    struct re_list *next = curr->next;
+
+    while (curr != NULL) {
+        re_mem_free(curr->msg);
+        re_mem_free(curr);
+        curr = next;
+        if (next != NULL) {
+            next = next->next;
+        }
+    }
+    q->cnt = 0;
+    re_mem_free(q);
+
+    re_unlock();
+    re_lock_deinit();
+}
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/rotary_encoder/rotary_encoder_queue1.h b/code/sdk/drivers/peripheral/rotary_encoder/rotary_encoder_queue1.h
new file mode 100644 (file)
index 0000000..e02ab04
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) @CompanyNameMagicTag 2021-2021. All rights reserved.
+ * Description: touch screen msg queue.
+ * Author: @CompanyNameTag
+ * Create: 2022-04-18
+ */
+
+#ifndef ROTARY_ENCODER_QUEUE1_H
+#define ROTARY_ENCODER_QUEUE1_H
+
+#include "soc_osal.h"
+#include "rotary_encoder_def.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+#define re_mem_free(sz)                 \
+    do {                                     \
+        if ((sz) != NULL) {               \
+            osal_kfree((sz));    \
+        }                                    \
+        (sz) = NULL;                      \
+    } while (0)
+
+struct re_list {
+    re_input_event_info *msg;
+    struct re_list *next;
+};
+
+typedef struct {
+    struct re_list *head;
+    struct re_list *tail;
+    uint32_t cnt;
+    uint32_t cap;
+} re_queue_t;
+
+re_queue_t *re_init_queue(uint32_t capacity);
+int32_t re_queue_get_length(re_queue_t *q);
+int32_t re_queue_is_empty(const re_queue_t *q);
+int32_t re_queue_is_full(const re_queue_t *q);
+int32_t re_de_queue(re_queue_t *q, re_input_event_info *msg);
+int32_t re_en_queue(re_queue_t *q, re_input_event_info *msg);
+void re_clear_queue(re_queue_t *q);
+void re_delete_queue(re_queue_t *q);
+
+#ifdef __cplusplus
+#if __cplusplus
+    }
+#endif
+#endif
+
+#endif
\ No newline at end of file
index ae02556..da5596b 100644 (file)
@@ -118,7 +118,7 @@ ext_errno tp_i2c_data_read(uint16_t reg_addr, uint8_t *data_buf, uint32_t data_l
     data.receive_len = data_len;
 
     for (retry = 0; retry < ZTW523_I2C_TIME_MAX; retry++) {
-        ret = uapi_i2c_master_writeread(FT6X46_I2C_BUS, ZTW523_I2C_ADDR, &data);
+        ret = uapi_i2c_master_writeread(FT6X46_I2C_BUS, FT6X46_I2C_ADDR, &data);
         if (ret == EXT_ERR_SUCCESS) {
             break;
         }
@@ -154,7 +154,7 @@ ext_errno tp_i2c_data_read(uint8_t reg_addr, uint8_t *data_buf, uint32_t data_le
     data.receive_len = data_len;
 
     for (retry = 0; retry < ZTW523_I2C_TIME_MAX; retry++) {
-        ret = uapi_i2c_master_writeread(FT6X46_I2C_BUS, ZTW523_I2C_ADDR, &data);
+        ret = uapi_i2c_master_writeread(FT6X46_I2C_BUS, FT6X46_I2C_ADDR, &data);
         if (ret == EXT_ERR_SUCCESS) {
             break;
         }
@@ -227,7 +227,7 @@ ext_errno tp_i2c_cmd_write(uint16_t cmd)
     data.receive_len = 0;
 
     for (retry = 0; retry < ZTW523_I2C_TIME_MAX; retry++) {
-        ret = uapi_i2c_master_write(FT6X46_I2C_BUS, ZTW523_I2C_ADDR, &data);
+        ret = uapi_i2c_master_write(FT6X46_I2C_BUS, FT6X46_I2C_ADDR, &data);
         if (ret == EXT_ERR_SUCCESS) {
             break;
         }
@@ -261,7 +261,7 @@ ext_errno tp_i2c_cmd_write(uint8_t cmd)
     data.receive_len = 0;
 
     for (retry = 0; retry < ZTW523_I2C_TIME_MAX; retry++) {
-        ret = uapi_i2c_master_write(FT6X46_I2C_BUS, ZTW523_I2C_ADDR, &data);
+        ret = uapi_i2c_master_write(FT6X46_I2C_BUS, FT6X46_I2C_ADDR, &data);
         if (ret == EXT_ERR_SUCCESS) {
             break;
         }
@@ -300,7 +300,7 @@ ext_errno tp_i2c_reg_write(uint16_t reg_addr, uint16_t reg_cfg)
     data.receive_len = 0;
 
     for (retry = 0; retry < ZTW523_I2C_TIME_MAX; retry++) {
-        ret = uapi_i2c_master_write(FT6X46_I2C_BUS, ZTW523_I2C_ADDR, &data);
+        ret = uapi_i2c_master_write(FT6X46_I2C_BUS, FT6X46_I2C_ADDR, &data);
         if (ret == EXT_ERR_SUCCESS) {
             break;
         }
@@ -350,7 +350,7 @@ ext_errno tp_i2c_data_write(uint16_t reg_addr, uint8_t *data_buf, uint32_t data_
     data.receive_len = 0;
 
     for (retry = 0; retry < ZTW523_I2C_TIME_MAX; retry++) {
-        ret = uapi_i2c_master_write(FT6X46_I2C_BUS, ZTW523_I2C_ADDR, &data);
+        ret = uapi_i2c_master_write(FT6X46_I2C_BUS, FT6X46_I2C_ADDR, &data);
         if (ret == EXT_ERR_SUCCESS) {
             break;
         }
@@ -399,7 +399,7 @@ ext_errno tp_i2c_data_write(uint8_t reg_addr, uint8_t *data_buf, uint16_t data_l
     data.receive_len = 0;
 
     for (retry = 0; retry < ZTW523_I2C_TIME_MAX; retry++) {
-        ret = uapi_i2c_master_write(FT6X46_I2C_BUS, ZTW523_I2C_ADDR, &data);
+        ret = uapi_i2c_master_write(FT6X46_I2C_BUS, FT6X46_I2C_ADDR, &data);
         if (ret == EXT_ERR_SUCCESS) {
             break;
         }
@@ -498,7 +498,7 @@ ext_errno ztw523_host_peripheral_init(ztw523_ctrl_attr *attr)
     }
 
     tp_print("TOUCH:i2c_id = %d  i2c_speed = %d  slave_addr  = 0x%x \r\n",
-        g_ctrl_attr.i2c_id, g_ctrl_attr.i2c_speed, ZTW523_I2C_ADDR);
+        g_ctrl_attr.i2c_id, g_ctrl_attr.i2c_speed, FT6X46_I2C_ADDR);
     g_host_dev_init_flag = true;
 
     return EXT_ERR_SUCCESS;
index 4a56285..5d994b8 100644 (file)
 #include "ft6x46_touch1.h"
 
 /* host peripheral definitions */
-#if CHIP_ASIC
-#define FT6X46_I2C_BUS            I2C_BUS_1
-#define FT6X46_INT_GPIO           S_AGPIO_R5
-#define ZTW523_RESET_GPIO         S_AGPIO_R4
-#else
-#define FT6X46_I2C_BUS            I2C_BUS_5
-#define FT6X46_INT_GPIO           S_MGPIO11
-#define ZTW523_RST_REG            0x5600201c
-#define ZTW523_RST_HIGH           3
-#define ZTW523_RST_LOW            0
-#endif
 
-#define ZTW523_I2C_ADDR           0x20
+// #define ZTW523_I2C_ADDR           0x20
 #define FT6X46_I2C_ADDR           0x38
 #define ZTW523_I2C_SPEED          I2C_SPEED_MODE_SS
 #define ZTW523_REG_BYTE_LEN       2
index e59cbcd..ad2d184 100644 (file)
@@ -27,6 +27,8 @@ extern "C" {
 #define CMD_GET_TOUCH_INFO     0
 #define TOUCH_SCREEN_GET_EVENT _IOWR(INPUT_TOUCH_MODULE_ID, CMD_GET_TOUCH_INFO, input_event_info)
 
+#define TP_DEBUG
+
 /* common definitions */
 #define tp_mem_free(sz)                   \
     do {                                  \
index f88f41d..a34945c 100644 (file)
@@ -449,6 +449,9 @@ void touch_screen_resume(void)
     if (ret != EXT_ERR_SUCCESS) { tp_err("touch resume ret=0x%x", ret); }
 #elif defined(TPTYPE_ZTW523)
     ztw523_resume();
+#elif defined(TPTYPE_FT6X46)
+    ztw523_resume();
+    // ft6x46_resume();
 #else
     ztw523_resume();
 #endif
@@ -473,6 +476,9 @@ void touch_screen_restart(void)
     tma525b_resume();
 #elif defined(TPTYPE_ZTW523)
     ztw523_resume();
+#elif defined(TPTYPE_FT6X46)
+    // ft6x46_resume();
+    ztw523_resume();
 #else
     ztw523_resume();
 #endif
index 8e8e6f6..a3bbc94 100755 (executable)
@@ -60,6 +60,25 @@ __attribute__((weak)) uint32_t button_close(void)
     return INPUT_FAILURE;
 }
 
+
+__attribute__((weak)) uint32_t encoder_register_report_event_cb(report_event_cb callback)
+{
+    (void)(callback);
+    return INPUT_FAILURE;
+}
+__attribute__((weak)) uint32_t encoder_unregister_report_event_cb(void)
+{
+    return INPUT_FAILURE;
+}
+__attribute__((weak)) uint32_t encoder_init(void)
+{
+    return INPUT_FAILURE;
+}
+__attribute__((weak)) uint32_t encoder_close(void)
+{
+    return INPUT_FAILURE;
+}
+
 static void InitInputDevices(void)
 {
     for (uint8_t i = 0; i < INDEV_TYPE_UNKNOWN; i++) {
@@ -67,6 +86,13 @@ static void InitInputDevices(void)
         g_inputDevs[i].initState = INDEV_UNINITIALIZED;
     }
 
+    /* Init Encoder Device */
+    g_inputDevs[INDEV_TYPE_ENCODER].type = INDEV_TYPE_ENCODER;
+    g_inputDevs[INDEV_TYPE_ENCODER].funcs.Init = encoder_init;
+    g_inputDevs[INDEV_TYPE_ENCODER].funcs.Close = encoder_close;
+    g_inputDevs[INDEV_TYPE_ENCODER].funcs.RegisterReportEventCb = encoder_register_report_event_cb;
+    g_inputDevs[INDEV_TYPE_ENCODER].funcs.UnregisterReportEventCb = encoder_unregister_report_event_cb;
+
     /* Init Touch Device */
     g_inputDevs[INDEV_TYPE_TOUCH].type = INDEV_TYPE_TOUCH;
     g_inputDevs[INDEV_TYPE_TOUCH].funcs.Init = ts_init;
diff --git a/code/sdk/middleware/services/gui/uikit/proprietary/src/ui/frameworks/dock/lite_encoder_device.cpp b/code/sdk/middleware/services/gui/uikit/proprietary/src/ui/frameworks/dock/lite_encoder_device.cpp
new file mode 100644 (file)
index 0000000..ce13d80
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2022 CompanyNameMagicTag.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "lite_encoder_device.h"
+#include "gfx_utils/input_event_info.h"
+#include "lite_input_distributer.h"
+
+namespace OHOS {
+bool LiteEncoderDevice::Read(DeviceData& data)
+{
+    (void)LiteInputDistributer::GetInstance()->GetEventData(data, InputDevType::INDEV_TYPE_ENCODER);
+    return false;
+}
+
+bool LiteEncoderDevice::IsEventEmpty()
+{
+    return LiteInputDistributer::GetInstance()->IsEventEmpty(InputDevType::INDEV_TYPE_ENCODER);
+}
+}
diff --git a/code/sdk/middleware/services/gui/uikit/proprietary/src/ui/frameworks/dock/lite_encoder_device.h b/code/sdk/middleware/services/gui/uikit/proprietary/src/ui/frameworks/dock/lite_encoder_device.h
new file mode 100644 (file)
index 0000000..757583c
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2022 CompanyNameMagicTag.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GRAPHIC_LITE_LITE_ENCODER_DEVICE_H
+#define GRAPHIC_LITE_LITE_ENCODER_DEVICE_H
+#include "dock/pointer_input_device.h"
+
+namespace OHOS {
+class LiteEncoderDevice : public PointerInputDevice {
+public:
+    LiteEncoderDevice() {}
+    ~LiteEncoderDevice() override {}
+    bool Read(DeviceData& data) override;
+    bool IsEventEmpty() override;
+};
+}
+#endif
index 1bb58c9..70947da 100755 (executable)
@@ -26,8 +26,9 @@
 #endif
 namespace OHOS {
 static DeviceData g_lastData = {0};
+static DeviceData g_lastEncoderData = {0};
 LiteInputDistributer::LiteInputDistributer()
-    : deviceData_({}) {}
+    : deviceData_({}),encoderData_({}) {}
 
 LiteInputDistributer::~LiteInputDistributer() {}
 
@@ -35,7 +36,9 @@ void LiteInputDistributer::SendRawEvent(const RawEvent& rawEvent)
 {
     RawEvent event = rawEvent;
     DisplayDev* displayDev = DisplayDev::GetInstance();
-    if ((event.type == InputDevType::INDEV_TYPE_TOUCH) &&
+    if ((event.type == InputDevType::INDEV_TYPE_TOUCH 
+    // || event.type == InputDevType::INDEV_TYPE_ENCODER
+    ) &&
         (displayDev->GetLayerRotateType(LAYER_0) == LayerRotateType::LAYER_ROTATE_90)) {
         LayerBuffer* buffer = displayDev->GetCurrentBuffer(LAYER_0);
         if (buffer == nullptr) {
@@ -55,6 +58,20 @@ void LiteInputDistributer::SendRawEvent(const RawEvent& rawEvent)
 void LiteInputDistributer::GetEventData(DeviceData& data, InputDevType type)
 {
     eventLock_.Lock();
+    
+    if (type == InputDevType::INDEV_TYPE_ENCODER) {
+        g_lastEncoderData = encoderData_;
+        if (IsShowPoint() && (encoderData_.timestamp != g_lastEncoderData.timestamp)) {
+            DfxTPGetEvent();
+        }
+        data.point.x = encoderData_.point.x;
+        data.point.y = encoderData_.point.y;
+        data.encoderDiff = encoderData_.encoderDiff;
+        data.state = encoderData_.state;
+        data.timestamp = encoderData_.timestamp;
+        eventLock_.Unlock();
+        return;
+    }
     if (type == InputDevType::INDEV_TYPE_TOUCH) {
         g_lastData = deviceData_;
         if (IsShowPoint() && (deviceData_.timestamp != g_lastData.timestamp)) {
@@ -89,6 +106,18 @@ void LiteInputDistributer::SetEventData(const RawEvent& event)
 {
     LowPowerManager::GetInstance()->ExitLowPower();
     eventLock_.Lock();
+    if (event.type == InputDevType::INDEV_TYPE_ENCODER) {
+        if (IsShowPoint()) {
+            DfxTPSetEvent(event.timestamp - encoderData_.timestamp);
+        }
+        encoderData_.encoderDiff = event.x;
+        encoderData_.point.x = event.x;
+        encoderData_.point.y = event.y;
+        encoderData_.state = event.state;
+        encoderData_.timestamp = event.timestamp;
+        eventLock_.Unlock();
+        return;
+    }
     if (event.type == InputDevType::INDEV_TYPE_TOUCH) {
         if (IsShowPoint()) {
             DfxTPSetEvent(event.timestamp - deviceData_.timestamp);
@@ -122,6 +151,8 @@ bool LiteInputDistributer::IsEventEmpty(InputDevType type)
         return ((g_lastData.state == 0) && (deviceData_.state == 0));
     } else if (type == InputDevType::INDEV_TYPE_KEY) {
         return keyList_.IsEmpty();
+    } else if (type == InputDevType::INDEV_TYPE_ENCODER){
+      //  return ((g_lastEncoderData.state == 0) && (encoderData_.state == 0));
     }
     return true;
 }
index 62983fa..99bcd70 100755 (executable)
@@ -20,6 +20,7 @@
 #include "hals/lite_input_distributer.h"\r
 #include "dock/lite_key_device.h"\r
 #include "dock/lite_touch_device.h"\r
+#include "dock/lite_encoder_device.h"\r
 #include "dfx/dfx_record.h"\r
 \r
 namespace OHOS {\r
@@ -52,6 +53,16 @@ static void EventCallback(InputDevData* data)
         event.state = data->state;\r
         event.timestamp = data->timestamp;\r
         event.type = InputDevType::INDEV_TYPE_TOUCH;\r
+    } else if (data->type == INDEV_TYPE_ENCODER) {\r
+         if (IsShowTPRaw()) {\r
+            GRAPHIC_LOGP("Encoder s: %u, x: %d, y: %d, diff: %d, t: %u", data->state, data->x, data->y,data->encoderDiff,\r
+                data->timestamp);\r
+        }\r
+        event.x = data->encoderDiff;\r
+        event.y = data->encoderDiff;\r
+        event.state = data->state;\r
+        event.timestamp = data->timestamp;\r
+        event.type = InputDevType::INDEV_TYPE_ENCODER;\r
     } else if (data->type == INDEV_TYPE_KEY) {\r
         if (!ConvertKeyId(data->keyId, &event.keyId)) {\r
             return;\r
@@ -68,7 +79,9 @@ static void EventCallback(InputDevData* data)
 void LiteInputHal::AddToIndevManager(uint8_t type)\r
 {\r
     InputDevice* dev = nullptr;\r
-    if (type == static_cast<uint8_t>(INDEV_TYPE_TOUCH)) {\r
+    if (type == static_cast<uint8_t>(INDEV_TYPE_ENCODER)) {\r
+        dev = new LiteEncoderDevice();\r
+    } else if (type == static_cast<uint8_t>(INDEV_TYPE_TOUCH)) {\r
         dev = new LiteTouchDevice();\r
     } else if (type == static_cast<uint8_t>(INDEV_TYPE_KEY)) {\r
         dev = new LiteKeyDevice();\r