/********************************************************************************************************
* @file AAA_Sensor.c
*
* @brief This is the source file for KMD SDK
*
* @author KMD GROUP
* @date 01,2022
*
* @par Copyright (c) 2022, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* 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 "AAA_public_config.h"
#if SENSOR_FUN_ENABLE_AAA
#define sif_spi_clk_low gpio_write(PIN_SIF_SCL, 0)
#define sif_spi_clk_high gpio_write(PIN_SIF_SCL, 1)
#define sif_spi_sda_low gpio_write(PIN_SIF_SDA, 0)
#define sif_spi_sda_high gpio_write(PIN_SIF_SDA, 1)
#define get_spi_sda_vaule gpio_read(PIN_SIF_SDA)
#define sif_spi_sda_output_enable gpio_set_output_en(PIN_SIF_SDA, 1)
#define sif_spi_sda_output_disable gpio_set_output_en(PIN_SIF_SDA, 0)
#define sif_spi_sda_input_enable gpio_set_input_en(PIN_SIF_SDA, 1)
#define sif_spi_sda_input_disable gpio_set_input_en(PIN_SIF_SDA, 0)
#if SENSOR_CS_ENABLE
#define sif_spi_cs_high gpio_write(PIN_SENSOR_CS,1)
#define sif_spi_cs_low gpio_write(PIN_SENSOR_CS,0)
#define CS_DELAY sleep_us(2)
#else
#define sif_spi_cs_high
#define sif_spi_cs_low
#define CS_DELAY
#endif
//CLOCK_DLY_6_CYC 370khz
#define DLY_200NS CLOCK_DLY_6_CYC//sleep_us(5)//asm("tnop");asm("tnop")
#define DLY_100NS CLOCK_DLY_10_CYC//sleep_us(5)//asm("tnop")
#define SENSOR_RECOVER_FAIL 1
////////////////////////////////////////////////////////////////////////////
// serial interface function
////////////////////////////////////////////////////////////////////////////
_attribute_data_retention_user u16 check_spi_counter;
_attribute_data_retention_user u8 check_resync_counter;
_attribute_data_retention_user u8 product_id1=0;
_attribute_data_retention_user u8 product_id2=0;
_attribute_data_retention_user u8 product_id3=0;
//u8 reg_0d;
_attribute_data_retention_user u8 sensor_type = 0xff;
_attribute_data_retention_user u8 mouse_cust_fct3065xy = 0;
_attribute_data_retention_user u8 dbg_sensor_cpi=0;
u8 dpi_max_level=3;
void sensor_set_wakeup_level_suspend(u8 enable)
{
cpu_set_gpio_wakeup(PIN_SIF_MOTION, 0, enable); //low wakeup suspend
}
void sensor_set_wakeup_level_deepsleep(u8 enable)
{
cpu_set_gpio_wakeup(PIN_SIF_MOTION, 0, enable); //low wakeup suspend
}
void sif_init(void)
{
}
void sensor_gpio_powerDownConfig()
{
gpio_setup_up_down_resistor(PIN_SIF_SCL, PM_PIN_PULLUP_1M);
if (gpio_read(PIN_SIF_SDA))
{
gpio_setup_up_down_resistor(PIN_SIF_SDA, PM_PIN_PULLUP_10K);
}
else
{
gpio_setup_up_down_resistor(PIN_SIF_SDA, PM_PIN_PULLDOWN_100K);
}
}
_attribute_ram_code_sec_ void sif_SendByte(u8 data)
{
u8 i = 0;
u8 buf = data;
for (i = 0; i < 8; i++)
{
sif_spi_clk_low;
gpio_write(PIN_SIF_SDA, buf & 0x80);
DLY_100NS;
sif_spi_clk_high;
buf <<= 1;
DLY_100NS;
}
}
_attribute_ram_code_sec_ u8 sif_ReadByte()
{
u8 i = 0;
u8 dat = 0;
for (i = 0; i < 8; i++)
{
sif_spi_clk_low;
dat <<= 1;
DLY_100NS;
sif_spi_clk_high;
DLY_100NS;
if (get_spi_sda_vaule)
{
dat |= 1;
}
}
return dat;
}
_attribute_ram_code_sec_ u8 I2C_PAN3204LL_ReadRegister(u8 cAddr)
{
u8 dat = 0;
u8 r = irq_disable();
sif_spi_sda_output_enable;
sif_spi_sda_input_disable;
sif_spi_cs_low;
CS_DELAY;
sif_SendByte(cAddr & 0x7f);
//gpio_setup_up_down_resistor(PIN_SIF_SDA, PM_PIN_PULLUP_1M);
sif_spi_sda_output_disable;// delay 5us
sif_spi_sda_input_enable; // delay 15us
//WaitUs(5); //this delay is necessary!
dat = sif_ReadByte();
//gpio_setup_up_down_resistor(PIN_SIF_SDA, PM_PIN_UP_DOWN_FLOAT);
CS_DELAY;
sif_spi_cs_high;
irq_restore(r);
return dat;
}
_attribute_ram_code_sec_ void I2C_PAN3204LL_WriteRegister(u8 cAddr, u8 cData)
{
u8 r = irq_disable();
gpio_set_output_en(PIN_SIF_SDA, 1);
gpio_set_input_en(PIN_SIF_SDA, 0);
sif_spi_cs_low;
CS_DELAY;
sif_SendByte((cAddr | 0x80));
//WaitUs(1);
sif_SendByte(cData);
CS_DELAY;
sif_spi_cs_high;
gpio_set_output_en(PIN_SIF_SDA, 0);
gpio_set_input_en(PIN_SIF_SDA, 1);
irq_restore(r);
}
//----------------------------------------------------------------------
// FUNCTION NAME: Sensor3204LL_Optimization_Setting
//
// DESCRIPTION:
// Do the optimization of the sensor PAN3204LL to consume less current.
// Also, if need, set a better tracking performance on Critical surfaces.
//
//----------------------------------------------------------------------
void DownloadConfigTable(const unsigned char *ptbl, unsigned int len)
{
unsigned int i, addr;
for (i = 0; i < len; i += 2)
{
addr = ptbl[0];
I2C_PAN3204LL_WriteRegister(addr, ptbl[1]);
ptbl += 2;
}
}
/*-------------------------PAW3809--------------------------*/
const unsigned char Config_PAW3809EK[]={
// 0x7F,0x00,
// 0x06,0x40,
// sleep_ms(5),
0x7F,0x00,
0x09,0x5A,
0x4F,0x00,
0x43,0x09,
0x7F,0x02,
0x0E,0xE0,
0x6E,0xBD,
0x74,0x9C,
0x73,0xAA,
0x1A,0xB4,
0x2B,0x06,
0x33,0x30,
0x39,0x20,
0x7A,0x40,
0x7F,0x04,
0x60,0xFB,
0x6E,0x05,
0x7F,0x06,
0x6E,0x05,
0x7F,0x03,
0x2D,0x01,
0x16,0x60,
0x17,0x60,
0x1C,0x60,
0x1D,0x60,
0x3D,0x26,
0x57,0x1C,
0x7C,0x23,
0x4C,0x00,
0x4D,0x07,
0x58,0x00,
0x7D,0x64,
0x01,0x00,
0x0A,0xAE,
0x10,0xAC,
0x38,0x23,
0x07,0x08,
0x08,0x08,
0x19,0x26,
0x1A,0x26,
0x1F,0x26,
0x20,0x26,
0x41,0x18,
0x44,0x08,
0x45,0x10,
0x51,0x42,
0x06,0x05,
0x18,0x36,
0x1E,0x36,
0x2D,0x00,
0x52,0x16,
0x7F,0x04,
0x26,0x02,
0x37,0x00,
0x39,0x07,
0x3C,0xC0,
0x3D,0xA0,
0x10,0x24,
0x04,0x45,
0x3E,0x40,
0x3F,0x01,
0x27,0x04,
0x1F,0x18,
0x20,0x1E,
0x21,0x18,
0x40,0x94,
0x41,0x02,
0x7F,0x05,
0x2D,0x01,
0x4C,0x00,
0x4D,0x07,
0x58,0x00,
0x38,0x23,
0x7C,0x23,
0x21,0x0E,
0x23,0x8A,
0x2D,0x00,
0x7F,0x06,
0x10,0x31,
0x40,0xA4,
0x41,0x03,
0x5B,0x0E,
0x5D,0x16,
0x7F,0x00,
0x4F,0x0A,
0x7F, 0x00,
0x09, 0x00,
};
/*-------------------------PAW3809--------------------------*/
const unsigned char Config_3205_TJ3T[] = {
0x09, 0x5A,
0x0D, 0x0A,
0x1B, 0x35,
0x1D, 0xDB,
0x28, 0xB4,
0x29, 0x46,
0x2A, 0x96,
0x2B, 0x8C,
0x2C, 0x6E,
0x2D, 0x64,
0x38, 0x5F,
0x39, 0x0F,
0x3A, 0x32,
0x3B, 0x47,
0x42, 0x10,
0x43, 0x09,
0x54, 0x2E,
0x55, 0xF2,
0x61, 0xF4,
0x63, 0x70,
0x75, 0x52,
0x76, 0x41,
0x77, 0xED,
0x78, 0x23,
0x79, 0x46,
0x7A, 0xE5,
0x7C, 0x48,
0x7D, 0x80,
0x7E, 0x77,
0x7F, 0x01,
0x0B, 0x00,
0x7F, 0x00,
0x09, 0x00,
};
const unsigned char Config_8650A[] = {
//0x7f , 0xa5,
//0x1c , 0x14,
//0x1f , 0x3a,
//0x7f , 0x00,
0xff, 0x27,
0xa0, 0xf0,
0xa1, 0x10,
0xa5, 0xaf,
0xac, 0x78,
0xad, 0x64,
0xae, 0x1a,
0xaf, 0x5e,
0xb0, 0x11,
0xb1, 0x94,
0xb5, 0xc8,
0xb6, 0x00,
0xff, 0x00,
/*
0xff, 0x27,
0xab, 0x40,
0xbe, 0xd1,
0xa0, 0x41,
0xa1, 0x41,
0xa5, 0x84,
0xa7, 0xff,
0xb5, 0xd0,
0xb6, 0x00,
0xff, 0x00,
*/
};
const unsigned char Config_VT108[] = { //KA8
0x09, 0x5a,
0x0d, 0x12,
0x0e, 0xc5,
0x09, 0x00,
};
const unsigned char Config_3212[] = {
0x09, 0x5a,
0x06, 0xa0,
0x26, 0x34,
#if SENSOR_DATA_LENGTH_12_BIT_ENABLE
0x19, 0x04, //new
#endif
0x09, 0x00,
};
const unsigned char Config_SG8670[] = { //SG8670
0x7F, 0x26,
0x09, 0x5A,
0x0f, 0x04,//12bit
0x28, 0x0e,//20240705//0x0C,// 04-0C最大曝光时间:150us
0x29, 0x10,//20240705//0xE4,// B0-E4
0x5B, 0x00,
0x4E, 0x1A,//0x23,
0x4F, 0x00,//0x28,
0x70, 0x00,//20240816//原无
0x7E, 0x01,
0x40, 0xFF,
0x41, 0xFF,
0x42, 0xFF,
0x43, 0xFF,
0x47, 0xAF,
0x4A, 0x00,//20240705//0x40,
0x4C, 0x04,//20240705//0x03,
0x4D, 0x00,
0x4E, 0x03,//20241017=0x05 //20240705=0x02, 原是0x03,调整过面,功耗
0x7E, 0x00,
//0x6e, 0x91, //400 dpi的设定
//0x6f, 0x11,
0x7F, 0x00,
0x09, 0x00,
};
typedef struct
{
const unsigned char *ptbl;
unsigned int len;
} SENSOR_OPT;
void sensor_resync()
{
gpio_write(PIN_SIF_SCL, 1);
WaitUs(3);
gpio_write(PIN_SIF_SCL, 0);
if ((sensor_type==SENSOR_3065)||(sensor_type==SENSOR_3065XY))
{
WaitUs(10000); //FCT3065-XY SCL Low 10ms, then high 512ms
gpio_write(PIN_SIF_SCL, 1);
WaitUs(40000);
}
else
{
WaitUs(5);
gpio_write(PIN_SIF_SCL, 1);
WaitUs(30000);
}
}
u8 sensor_check_id()
{
u8 reg0=0;
reg0 = I2C_PAN3204LL_ReadRegister(REG_PAN3204LL_PRODUCT_ID1);
if((reg0!=0x30)&&(reg0!=0x31)&&(reg0!=0x58)&&(reg0!=0x18)&&(reg0!=0x33))
{
sensor_resync();
return 0;
}
return 1;
}
int OPTSensor_resync(u32 retry)
{
//return 0;
for(u16 i=0;i<retry;i++)
{
#if (MODULE_WATCHDOG_ENABLE)
wd_clear();
#endif
if(sensor_check_id())
{
return 1;
}
}
return 0;
}
static int sensor_type_identify()
{
int sensor_type = SENSOR_3205_TJNT;
printf("product_id1=%d,product_id2=%d,sensor_type=%d\n",product_id1,product_id2,sensor_type);
if(product_id1==0x18)
{
dpi_max_level=4;
return SENSOR_OM18;
}
else if((product_id1==0x58)&&(product_id2==0x59))
{
dpi_max_level=4;
return SENSOR_KA8G2;
}
else if((product_id1==0x30))
{
if((product_id2)==0x02)
{
dpi_max_level=4;
return SENSOR_PAW3212;
}
else if((product_id2)==0x5a)
{
dpi_max_level =4;
return SENSOR_SG8670;//SG8670 #define SG8670_PRODUCT_ID2 0x5a //add by hunter
}
else if((product_id2&0xf0)==0x50)
{
if(product_id2==0x54)
{
return SENSOR_VT108;
}
else
{
return SENSOR_M8650A;
}
}
else if((product_id2&0xf0)==0xd0)//
{
return SENSOR_3205_TJ3T;
}
}
else if((product_id1==0x31))
{
if((product_id2)==0x00)
{
return SENSOR_3065;
}
else if((product_id2)==0x70)
{
return SENSOR_3065XY;
}
}
else if(product_id1==0x33)
{
if(product_id2==0x11)
{
return SENSOR_3809EK;
}
}
return sensor_type;
}
void om18_Optimization_Setting()
{
u8 var1,var2,var3;
I2C_PAN3204LL_WriteRegister(0x09,0x5a);
I2C_PAN3204LL_WriteRegister(0x62,0x63);
I2C_PAN3204LL_WriteRegister(0x6e,0x63);
I2C_PAN3204LL_WriteRegister(0x6f,0x63);
I2C_PAN3204LL_WriteRegister(0x70,0x63);
I2C_PAN3204LL_WriteRegister(0x71,0x63);
I2C_PAN3204LL_WriteRegister(0x56,0x08);
var1=I2C_PAN3204LL_ReadRegister(0x43)&0x0f;
var2=I2C_PAN3204LL_ReadRegister(0x45)&0x7f;
var3=I2C_PAN3204LL_ReadRegister(0x46)&0x7f;
I2C_PAN3204LL_WriteRegister(0x43,var1);
I2C_PAN3204LL_WriteRegister(0x45,var2);
I2C_PAN3204LL_WriteRegister(0x46,var3);
I2C_PAN3204LL_WriteRegister(0x56,0);
#if SENSOR_DATA_LENGTH_12_BIT_ENABLE
I2C_PAN3204LL_WriteRegister(0x19,0x14); //14
#else
I2C_PAN3204LL_WriteRegister(0x19,0x10);
#endif
I2C_PAN3204LL_WriteRegister(0x09,0x00);
}
void KA8G2_Optimization_Setting()
{
I2C_PAN3204LL_WriteRegister(0x09,0xA5);
I2C_PAN3204LL_WriteRegister(0x46,0x34); // ???? spi ??????
I2C_PAN3204LL_WriteRegister(0x19,0x00);
I2C_PAN3204LL_WriteRegister(0x60,0x07);
I2C_PAN3204LL_WriteRegister(0x69,0x04);
I2C_PAN3204LL_WriteRegister(0x7D,0x20);
I2C_PAN3204LL_WriteRegister(0x7E,0x00);
//I2C_PAN3204LL_WriteRegister(0x09,0x00);
I2C_PAN3204LL_WriteRegister(0x0D,0x1B);
I2C_PAN3204LL_WriteRegister(0x0E,0x1B);
I2C_PAN3204LL_WriteRegister(0x6E,0x1c); //disable
//I2C_PAN3204LL_WriteRegister(0x6E,0x14);// eanble inter Internal resistance
#if SENSOR_DATA_LENGTH_12_BIT_ENABLE
I2C_PAN3204LL_WriteRegister(0x19,0x04);
#endif
I2C_PAN3204LL_WriteRegister(0x09,0x00);
}
//called when power on, or mouse waked up from deep-sleep
unsigned int OPTSensor_Init(unsigned int poweron)
{
// Do the full chip reset.
u8 reg6=0;
// sensor_type = analog_read(DEEP_ANA_REG6);
sif_init();
OPTSensor_resync(33);
Sensor3204_Wakeup(sensor_type);
reg6=I2C_PAN3204LL_ReadRegister(REG_PAN3204LL_CONFIGURATION)|0x80;
I2C_PAN3204LL_WriteRegister(REG_PAN3204LL_CONFIGURATION, reg6);
WaitUs(25000);
//get sensor id
product_id1=0x33;
product_id2=0x11;
I2C_PAN3204LL_WriteRegister(0x00, product_id1);
I2C_PAN3204LL_WriteRegister(0x01, product_id2);
// product_id1 = I2C_PAN3204LL_ReadRegister(REG_PAN3204LL_PRODUCT_ID1); //power-on must re-read product_id1, or it would make mistake
// product_id2 = I2C_PAN3204LL_ReadRegister(REG_PAN3204LL_PRODUCT_ID2);
printf("product_id3=%d,product_id4=%d\n",product_id1,product_id2);
// product_id3 = I2C_PAN3204LL_ReadRegister(0x60); //
sensor_type = sensor_type_identify();//3205/3605/VT108=KA8/M8650A/OM18/YS8009/KA8G2/3212/S201B===800-1200-1600
printf("---sensor_type=%d.\n",sensor_type);
// if(poweron)
{
if(sensor_type==SENSOR_3205_TJNT)
{
//DownloadConfigTable(Config_3205,sizeof(Config_3205));
}
else if(sensor_type==SENSOR_3205_TJ3T)
{
DownloadConfigTable(Config_3205_TJ3T,sizeof(Config_3205_TJ3T));
}
else if(sensor_type==SENSOR_3065)
{
//DownloadConfigTable(Config_AN3205,sizeof(Config_AN3205));
}
else if(sensor_type==SENSOR_VT108)
{
DownloadConfigTable(Config_VT108,sizeof(Config_VT108));
}
else if(sensor_type==SENSOR_M8650A)
{
DownloadConfigTable(Config_8650A,sizeof(Config_8650A));
}
else if(sensor_type==SENSOR_OM18)
{
om18_Optimization_Setting();
}
else if(sensor_type==SENSOR_KA8G2)
{
KA8G2_Optimization_Setting();
}
else if(sensor_type==SENSOR_PAW3212)
{
DownloadConfigTable(Config_3212, sizeof(Config_3212));
}
else if(sensor_type==SENSOR_SG8670)//SG8670
{
DownloadConfigTable(Config_SG8670, sizeof(Config_SG8670));//download config table
u8 reg_temp=(I2C_PAN3204LL_ReadRegister(0x06)&0x7f);
I2C_PAN3204LL_WriteRegister(0x06,(reg_temp|0x80));
}
else if(sensor_type==SENSOR_3809EK)
{
DownloadConfigTable(Config_PAW3809EK, sizeof(Config_PAW3809EK));
}
}
return sensor_type;
}
int Xcnt=0;
int Ycnt=0;
int Bak_X0=0;
int Bak_Y0=0;
void dpi_4000_proc()
{
int Dpi_Temp=0;
char Residue=0;
Xcnt=ms_data.x;
Ycnt=ms_data.y;
Dpi_Temp = Bak_X0;
Bak_X0 = Xcnt;
Residue = Dpi_Temp%2;
Xcnt = Dpi_Temp/2+Bak_X0;
Bak_X0 = Bak_X0+Residue;
Dpi_Temp = Bak_Y0;
Bak_Y0 = Ycnt;
Residue = Dpi_Temp%2;
Ycnt = Dpi_Temp/2+Bak_Y0;
Bak_Y0 = Bak_Y0+Residue;
ms_data.x=Xcnt;
ms_data.y=Ycnt;
}
int xsum=0,ysum=0;
u8 debug_xy=2;
unsigned int OPTSensor_motion_report( u32 no_overflow )
{
unsigned int optical_status = 0;
unsigned int reg_x, reg_y, reg_X_Y_H;
//sensor ph5205 no overflow read
if(( sensor_type==SENSOR_PAW3212)||( sensor_type==SENSOR_OM18)||( sensor_type==SENSOR_KA8G2)||( sensor_type==SENSOR_SG8670))
{
no_overflow=1;
}
ms_data.x = 0;
ms_data.y = 0;
if (OPTSensor_resync(33)==0)
{
return 0;
}
#if SENSOR_MOTION_ENABLE
if (gpio_read(PIN_SIF_MOTION))
{
return 0;
}
#endif
optical_status = I2C_PAN3204LL_ReadRegister(REG_PAN3204LL_MOTION_STATUS);
if((optical_status & MOTION_STATUS_MOT) || (no_overflow && ((optical_status & MOTION_STATUS_DXOVF) || (optical_status & MOTION_STATUS_DYOVF))))
{
#if SENSOR_DATA_LENGTH_12_BIT_ENABLE
if((sensor_type==SENSOR_OM18)||(sensor_type==SENSOR_PAW3212)||(sensor_type==SENSOR_KA8G2)||( sensor_type==SENSOR_SG8670))
{
reg_X_Y_H = I2C_PAN3204LL_ReadRegister(REG_PAN3204LL_DELTA_XY_H);
reg_x = I2C_PAN3204LL_ReadRegister(REG_PAN3204LL_DELTA_X)|((reg_X_Y_H&0xF0)<<4); // DIRECTION_CLOCK_12 X
reg_y = I2C_PAN3204LL_ReadRegister(REG_PAN3204LL_DELTA_Y)|((reg_X_Y_H&0x0F)<<8); // DIRECTION_CLOCK_12 Y
if(reg_x&0x0800)
{
ms_data.x=0xf000|reg_x;
}
else
{
ms_data.x=reg_x;
}
if(reg_y&0x0800)
{
ms_data.y=0xf000|reg_y;
}
else
{
ms_data.y=reg_y;
}
if((sensor_type==SENSOR_SG8670)&&(dpi_value>0))//SG8670
{
//int xsum=0,ysum=0;
if(dpi_value>1)
{
debug_xy=2;
}
else
{
debug_xy=5;
}
if((abs(ms_data.x)>debug_xy)||(abs(ms_data.y)>debug_xy))
{
xsum+=ms_data.x;
if(ms_data.x>0)
ms_data.x=(xsum+1)/3;
else
ms_data.x=(xsum-1)/3;
xsum-=ms_data.x;
ysum+=ms_data.y;
if(ms_data.y>0)
ms_data.y=(ysum+1)/3;
else
ms_data.y=(ysum-1)/3;
ysum-=ms_data.y;
}
//if(dpi_value==3)
// dpi_4000_proc();
}
}
else
#endif
{
reg_x = I2C_PAN3204LL_ReadRegister(REG_PAN3204LL_DELTA_X); // DIRECTION_CLOCK_12 X
reg_y = I2C_PAN3204LL_ReadRegister(REG_PAN3204LL_DELTA_Y); // DIRECTION_CLOCK_12 Y
if(reg_x==0x80)
reg_x = 0x81;
if(reg_y==0x80)
reg_y = 0x81;
if( !no_overflow ){
if(optical_status & MOTION_STATUS_DXOVF)
reg_x = ((signed char)reg_x>=0)? 0x81:0x7f; //x overflow, current<0,0x7f, current>0, 0xff
if(optical_status & MOTION_STATUS_DYOVF)
reg_y = ((signed char)reg_y>=0)? 0x81:0x7f; //y overflow, current<0,0x7f, current>0, 0xff
}
if(reg_x&0x0080)
{
ms_data.x=0xff00|reg_x;
}
else
{
ms_data.x=reg_x;
}
if(reg_y&0x0080)
{
ms_data.y=0xff00|reg_y;
}
else
{
ms_data.y=reg_y;
}
}
return 1;
}
else{
xsum=0;
ysum=0;
return 0;
}
}
// Must clear SLP_ENH bit in the OPERATION_MODE register before using Power-Down mode.
void OPTSensor_Shutdown(void)
{
u8 reg06=0;
for(u8 i=0;i<8;i++)
{
reg06=I2C_PAN3204LL_ReadRegister(REG_PAN3204LL_CONFIGURATION);
I2C_PAN3204LL_WriteRegister(REG_PAN3204LL_CONFIGURATION,reg06|0x08);
sleep_us(1000);
reg06=I2C_PAN3204LL_ReadRegister(REG_PAN3204LL_CONFIGURATION);
if(reg06&0x08)
{
break;
}
else
{
OPTSensor_resync(1);
}
}
sensor_gpio_powerDownConfig();
}
void sensor3204_cpi_set(u8 dpi_val)
{
for (u8 i = 0; i < 32; i++)
{
u8 reg_1 = 0, reg_2 = 0;
reg_2 = (I2C_PAN3204LL_ReadRegister(REG_PAN3204LL_CONFIGURATION) & 0xf8) | (dpi_val & 0x07);
I2C_PAN3204LL_WriteRegister(REG_PAN3204LL_CONFIGURATION, reg_2);
reg_1 = I2C_PAN3204LL_ReadRegister(REG_PAN3204LL_CONFIGURATION);
if (reg_1 == reg_2)
{
return;
}
}
}
//M413 (8670)双模锂电款在原来DPI是:1200/1600(默认)/2000/2400
//这个基础上新增一版1200-2400默认-3200-4000(原来的2400DPI程序不保留)
const u8 SG8670_dpi_tbl[] =//*23
{
50, //1196 //52, //1196
98, //2400 //69, //1587
87, //2100 //86, //1978
108,// 2666 //104, //2392
};
void SG8670_CPI_set(u8 dpi_val)
{
for (u8 i = 0; i < 16; i++)
{
u8 reg_1 = 0, reg_2 = 0;
I2C_PAN3204LL_WriteRegister(0x7f,0x26);
I2C_PAN3204LL_WriteRegister(0x09,0x5a);
I2C_PAN3204LL_WriteRegister(0x7e,0x00);
I2C_PAN3204LL_WriteRegister(0x6e, (0x80|dpi_val));
I2C_PAN3204LL_WriteRegister(0x6f, dpi_val);
reg_1 = I2C_PAN3204LL_ReadRegister(0x6e);
reg_2 = I2C_PAN3204LL_ReadRegister(0x6f);
I2C_PAN3204LL_WriteRegister(0x7f,0x00);
I2C_PAN3204LL_WriteRegister(0x09,0x00);
if ((reg_2 == dpi_val))
{
return;
}
}
}
const u8 KA8G2_dpi_tbl[] =
{
20, //1200
27, //1620
34, //2040
40, //2400
//14, //840
//20, //1200
//27, //1620
//40, //2400
};
void KA8G2_CPI_set(u8 dpi_val)
{
for (u8 i = 0; i < 16; i++)
{
u8 reg_1 = 0, reg_2 = 0;
I2C_PAN3204LL_WriteRegister(0x09,0xA5);
I2C_PAN3204LL_WriteRegister(0x0d, dpi_val);
I2C_PAN3204LL_WriteRegister(0x0e, dpi_val);
reg_1 = I2C_PAN3204LL_ReadRegister(0x0d);
reg_2 = I2C_PAN3204LL_ReadRegister(0x0e);
I2C_PAN3204LL_WriteRegister(0x09,0x00);
if ((reg_1 == reg_2)&&(reg_2 == dpi_val))
{
return;
}
}
}
//1200/1600(默认)/2000/2400
const u8 paw3212_dpi_tbl[] =
{
33, // cpi_1300 = 32*38 = 1254
43, // cpi_1600 = 42*38 = 1634
53, // cpi_2000 = 53*38 = 2014
63, // cpi_2400 = 63*38 = 2394
//22, // cpi_800 = 22*38 = 836, step = 38
//32, // cpi_1200 = 32*38 = 1216
//42, // cpi_1600 = 42*38 = 1596
//63, // cpi_2400 = 63*38 = 2394
// cpi_3600 Counterfeiting
};
void paw3212_CPI_set(u8 dpi_val)
{
for (u8 i = 0; i < 16; i++)
{
u8 reg_1 = 0, reg_2 = 0;
I2C_PAN3204LL_WriteRegister(0x09,0x5A);
I2C_PAN3204LL_WriteRegister(0x0d, dpi_val);
I2C_PAN3204LL_WriteRegister(0x0e, dpi_val);
reg_1 = I2C_PAN3204LL_ReadRegister(0x0d);
reg_2 = I2C_PAN3204LL_ReadRegister(0x0e);
I2C_PAN3204LL_WriteRegister(0x09,0x00);
if ((reg_1 == reg_2)&&(reg_2 == dpi_val))
{
return;
}
}
}
const u8 om18_dpi_tbl[] =
{
33, // cpi_1300 = 32*38 = 1254
43, // cpi_1600 = 42*38 = 1634
53, // cpi_2000 = 53*38 = 2014
63, // cpi_2400 = 63*38 = 2394
//22, // cpi_800 = 22*38 = 836, step = 38
//32, // cpi_1200 = 32*38 = 1216
//42, // cpi_1600 = 42*38 = 1596
//63, // cpi_2400 = 63*38 = 2394
// cpi_3600 Counterfeiting
};
void om18_CPI_set(u8 dpi_val)
{
for (u8 i = 0; i < 16; i++)
{
u8 reg_1 = 0, reg_2 = 0;
I2C_PAN3204LL_WriteRegister(0x09,0x5a);
I2C_PAN3204LL_WriteRegister(0x10, dpi_val);
I2C_PAN3204LL_WriteRegister(0x11, dpi_val);
reg_1 = I2C_PAN3204LL_ReadRegister(0x10);
reg_2 = I2C_PAN3204LL_ReadRegister(0x11);
I2C_PAN3204LL_WriteRegister(0x09,0x00);
if ((reg_1 == reg_2)&&(reg_2 == dpi_val))
{
return;
}
}
}
_attribute_data_retention_user u8 xy_multiple_flag = 0;
void sensor_dpi_set(u8 cpi_ctrl)//800-1200-1600
{
u8 temp_cpi=cpi_ctrl;
xy_multiple_flag=0;
if((sensor_type==SENSOR_3205_TJ3T)||(sensor_type==SENSOR_3205_TJNT)||(sensor_type==SENSOR_3065))
{
if(0==temp_cpi)
temp_cpi =1;
else
temp_cpi +=2;
sensor3204_cpi_set(temp_cpi);
}
else if((sensor_type==SENSOR_3065XY)||(sensor_type==SENSOR_M8650A))
{
if(0!=temp_cpi)
temp_cpi +=1;
sensor3204_cpi_set(temp_cpi);
}
else if(sensor_type==SENSOR_VT108)//KA8
{
if(0==temp_cpi)
temp_cpi =3;
else
temp_cpi +=4;
sensor3204_cpi_set(temp_cpi);
}
else if(sensor_type==SENSOR_OM18)
{
om18_CPI_set(om18_dpi_tbl[cpi_ctrl]);
}
else if(sensor_type==SENSOR_KA8G2)
{
KA8G2_CPI_set(KA8G2_dpi_tbl[cpi_ctrl]);
}
else if(sensor_type==SENSOR_PAW3212)
{
paw3212_CPI_set(paw3212_dpi_tbl[cpi_ctrl]);
}
else if(sensor_type==SENSOR_SG8670)//SG8670
{
SG8670_CPI_set(SG8670_dpi_tbl[cpi_ctrl]);//+4//4=1000,5==1200,6==1600,7==2300
if((2==cpi_ctrl)||(3==cpi_ctrl))
xy_multiple_flag=MULTIPIPE_1_DOT_5;
}
}
void btn_dpi_set()
{
dpi_value++;
if (dpi_value >= dpi_max_level)
{
dpi_value = 0;
}
flash_dpi_info.bt_dpi =dpi_value;
save_user_info_flash();
sensor_dpi_set(dpi_value);
#if BLT_APP_LED_ENABLE
dpi_led_set(dpi_value + 1);
#endif
}
int Sensor3204_Wakeup(u32 sensor)
{
#if SENSOR_SHUT_DOWN_ENABLE
int timeout = 0;
u8 debug_reg5;
I2C_PAN3204LL_WriteRegister(REG_PAN3204LL_CONFIGURATION, 2); //clear BIT(3) to exit Power down mode, deault cpi-rate-2
do
{
I2C_PAN3204LL_WriteRegister(REG_PAN3204LL_OPERATION_MODE, WAKEUP_3204); //sleep enable and wakeup
debug_reg5 = I2C_PAN3204LL_ReadRegister(REG_PAN3204LL_OPERATION_MODE);
OPTSensor_resync(33);
#if (MODULE_WATCHDOG_ENABLE)
wd_clear(); //clear watch dog
#endif
}
while ((debug_reg5 != WAKEUP_3204) && (++timeout < 32));
#endif
return 1;
}
void check_sensor_dircet(u8 sensor_dir)
{
s16 temp;
if (sensor_dir == SENSOR_DIRECTION_CLOCK_3)
{
temp = ms_data.y;
ms_data.y = ms_data.x;
ms_data.x = temp;
}
else if (sensor_dir == SENSOR_DIRECTION_CLOCK_6)
{
ms_data.x = -ms_data.x;
}
else if (sensor_dir == SENSOR_DIRECTION_CLOCK_9)
{
temp = ms_data.y;
ms_data.y = -ms_data.x;
ms_data.x = -temp;
}
else if (sensor_dir == SENSOR_DIRECTION_CLOCK_12)
{
ms_data.y = -ms_data.y;
}
}
_attribute_data_retention_user int sm_sum_x=0;
_attribute_data_retention_user int sm_pre_x=0;
_attribute_data_retention_user int sm_sum_y=0;
_attribute_data_retention_user int sm_pre_y=0;
void iir_smoother()
{
sm_sum_x = sm_sum_x - sm_pre_x + ms_data.x;
sm_pre_x = sm_sum_x / 2;
ms_data.x = sm_pre_x;
sm_sum_y = sm_sum_y - sm_pre_y + ms_data.y;
sm_pre_y = sm_sum_y / 2;
ms_data.y = sm_pre_y;
}
static inline void iir_smoother_clear(void)
{
// xsum=0;
// ysum=0;
// Bak_X0=0;
// Bak_Y0=0;
sm_sum_x = 0;
sm_pre_x = 0;
sm_sum_y = 0;
sm_pre_y = 0;
}
#define sm_dyn_pth1 6
#define sm_dyn_pth2 4
u8 adaptive_smoother()
{
_attribute_data_retention_user static u8 asm_flg = 0;
_attribute_data_retention_user static u32 sm_last_smoother_tick = 0;
//auto clear asm sum when no data for a long time
if (asm_flg && clock_time_exceed(sm_last_smoother_tick, 100000))
{
asm_flg = 0;
iir_smoother_clear();
}
if (!asm_flg)
{
if ((abs(ms_data.x) > sm_dyn_pth1) || (abs(ms_data.y) > sm_dyn_pth1))
{
asm_flg = 1;
iir_smoother();
}
else
{
asm_flg = 0;
iir_smoother_clear();
}
}
else
{
if ((abs(ms_data.x) < sm_dyn_pth2) && (abs(ms_data.y) < sm_dyn_pth2))
{
asm_flg = 0;
iir_smoother_clear();
}
else
{
asm_flg = 1;
iir_smoother();
}
}
if (asm_flg)
{
sm_last_smoother_tick = clock_time();
}
return asm_flg;
}
#endif