356 lines
8.9 KiB
C
356 lines
8.9 KiB
C
#include "PAW3395.h"
|
||
#include "Delay.h"
|
||
#include "usr_spi.h"
|
||
static void Power_Up_Initializaton_Register_Setting(void);
|
||
|
||
|
||
/*
|
||
*严格按照开机顺序执行:
|
||
* 虽然芯片执行内部上电自复位,但仍建议将Power_Up_Reset
|
||
* 每次上电时都会写入寄存器。推荐的芯片上电顺序如下:
|
||
* 1. 以任何顺序为VDD和VDDIO供电,每次供电之间的延迟不超过100ms。确保所有供应稳定。
|
||
* 2. 等待至少50毫秒。
|
||
* 3. 将NCS拉高,然后拉低以重置SPI端口。
|
||
* 4. 将0x5A写入Power_Up_Reset寄存器(或者切换NRESET引脚)。
|
||
* 5. 等待至少5ms。
|
||
* 6. 加载上电初始化寄存器设置。
|
||
* 7. 无论运动位状态如何,都读取寄存器0x02、0x03、0x04、0x05和0x06一次。
|
||
*
|
||
*
|
||
*
|
||
*
|
||
*
|
||
*/
|
||
void Power_up_sequence(void)
|
||
{
|
||
uint8_t reg_it;
|
||
//Wait for at least 50ms(2.等待至少50毫秒。)
|
||
delay_ms(50);
|
||
// drive NCS high, then low to reset the SPI port(3.重置SPI端口)
|
||
CS_Low;
|
||
delay_125_ns(PAW3395_TIMINGS_NCS_SCLK);
|
||
CS_High;
|
||
delay_125_ns(PAW3395_TIMINGS_NCS_SCLK);
|
||
CS_Low;
|
||
delay_125_ns(PAW3395_TIMINGS_NCS_SCLK);
|
||
|
||
// Write 0x5A to POWER_UP_Reset register(4.将0x5A写入Power_Up_Reset寄存器)
|
||
writr_register(PAW3395_SPIREGISTER_POWERUPRESET
|
||
,PAW3395_POWERUPRESET_POWERON);
|
||
//Wait for at least 5ms(5.等待至少5ms)
|
||
delay_ms(5);
|
||
//Load Power-up initialization register setting(6.加载上电初始化寄存器设置)
|
||
Power_Up_Initializaton_Register_Setting();
|
||
CS_High;
|
||
delay_125_ns(PAW3395_TIMINGS_NCS_SCLK);
|
||
// read register from 0x02 to 0x06(7.无论运动位状态如何,都读取寄存器0x02、0x03、0x04、0x05和0x06一次)
|
||
for(reg_it=0x02; reg_it<=0x06; reg_it++)
|
||
{
|
||
read_register(reg_it);
|
||
delay_us(PAW3395_TIMINGS_SRWSRR);
|
||
}
|
||
//片选拉高,本次SPI通讯结束
|
||
CS_High;
|
||
delay_125_ns(PAW3395_TIMINGS_BEXIT);
|
||
}
|
||
|
||
|
||
/*
|
||
*严格执行启动Motion Burst的程序:
|
||
* 1. 降低NCS。
|
||
* 2. 等待tNCS-SCLK
|
||
* 3. 发送Motion_Burst地址(0x16)。发送此地址后,MOSI应保持静态(高电平或低电平),直到突发传输完成。
|
||
* 4. 等待tSRAD
|
||
* 5. 开始连续读取最多12个字节的SPI数据。可以通过将NCS拉高持续at来终止运动突发至少tBEXIT。
|
||
* 6. 要读取新的运动突发数据,请从步骤1开始重复。
|
||
*
|
||
*注意:
|
||
* 即使在运行或静止模式下,也可以从Burst_Motion_Read寄存器读取运动突发数据。
|
||
*
|
||
*/
|
||
void Motion_Burst(uint8_t *buffer)
|
||
{
|
||
//Lower NCS
|
||
CS_Low;
|
||
//Wait for t(NCS-SCLK)
|
||
delay_125_ns(PAW3395_TIMINGS_NCS_SCLK);
|
||
//Send Motion_Brust address(0x16)
|
||
SPI_SendReceive(PAW3395_SPIREGISTER_MotionBurst); //读
|
||
//Wait for tSRAD
|
||
delay_us(PAW3395_TIMINGS_SRAD);
|
||
//Start reading SPI data continuously up to 12 bytes.
|
||
for(uint8_t i = 0;i < 12;i++)
|
||
{
|
||
buffer[i] = SPI_SendReceive(0x00);
|
||
}
|
||
CS_High;
|
||
delay_125_ns(PAW3395_TIMINGS_BEXIT);
|
||
}
|
||
|
||
/*
|
||
*上电初始化寄存器设置
|
||
*
|
||
*/
|
||
static void Power_Up_Initializaton_Register_Setting(void)
|
||
{
|
||
uint8_t read_tmp;
|
||
uint8_t i ;
|
||
writr_register(0x7F ,0x07);
|
||
writr_register(0x40 ,0x41);
|
||
writr_register(0x7F ,0x00);
|
||
writr_register(0x40 ,0x80);
|
||
writr_register(0x7F ,0x0E);
|
||
writr_register(0x55 ,0x0D);
|
||
writr_register(0x56 ,0x1B);
|
||
writr_register(0x57 ,0xE8);
|
||
writr_register(0x58 ,0xD5);
|
||
writr_register(0x7F ,0x14);
|
||
writr_register(0x42 ,0xBC);
|
||
writr_register(0x43 ,0x74);
|
||
writr_register(0x4B ,0x20);
|
||
writr_register(0x4D ,0x00);
|
||
writr_register(0x53 ,0x0E);
|
||
writr_register(0x7F ,0x05);
|
||
writr_register(0x44 ,0x04);
|
||
writr_register(0x4D ,0x06);
|
||
writr_register(0x51 ,0x40);
|
||
writr_register(0x53 ,0x40);
|
||
writr_register(0x55 ,0xCA);
|
||
writr_register(0x5A ,0xE8);
|
||
writr_register(0x5B ,0xEA);
|
||
writr_register(0x61 ,0x31);
|
||
writr_register(0x62 ,0x64);
|
||
writr_register(0x6D ,0xB8);
|
||
writr_register(0x6E ,0x0F);
|
||
|
||
writr_register(0x70 ,0x02);
|
||
writr_register(0x4A ,0x2A);
|
||
writr_register(0x60 ,0x26);
|
||
writr_register(0x7F ,0x06);
|
||
writr_register(0x6D ,0x70);
|
||
writr_register(0x6E ,0x60);
|
||
writr_register(0x6F ,0x04);
|
||
writr_register(0x53 ,0x02);
|
||
writr_register(0x55 ,0x11);
|
||
writr_register(0x7A ,0x01);
|
||
writr_register(0x7D ,0x51);
|
||
writr_register(0x7F ,0x07);
|
||
writr_register(0x41 ,0x10);
|
||
writr_register(0x42 ,0x32);
|
||
writr_register(0x43 ,0x00);
|
||
writr_register(0x7F ,0x08);
|
||
writr_register(0x71 ,0x4F);
|
||
writr_register(0x7F ,0x09);
|
||
writr_register(0x62 ,0x1F);
|
||
writr_register(0x63 ,0x1F);
|
||
writr_register(0x65 ,0x03);
|
||
writr_register(0x66 ,0x03);
|
||
writr_register(0x67 ,0x1F);
|
||
writr_register(0x68 ,0x1F);
|
||
writr_register(0x69 ,0x03);
|
||
writr_register(0x6A ,0x03);
|
||
writr_register(0x6C ,0x1F);
|
||
|
||
writr_register(0x6D ,0x1F);
|
||
writr_register(0x51 ,0x04);
|
||
writr_register(0x53 ,0x20);
|
||
writr_register(0x54 ,0x20);
|
||
writr_register(0x71 ,0x0C);
|
||
writr_register(0x72 ,0x07);
|
||
writr_register(0x73 ,0x07);
|
||
writr_register(0x7F ,0x0A);
|
||
writr_register(0x4A ,0x14);
|
||
writr_register(0x4C ,0x14);
|
||
writr_register(0x55 ,0x19);
|
||
writr_register(0x7F ,0x14);
|
||
writr_register(0x4B ,0x30);
|
||
writr_register(0x4C ,0x03);
|
||
writr_register(0x61 ,0x0B);
|
||
writr_register(0x62 ,0x0A);
|
||
writr_register(0x63 ,0x02);
|
||
writr_register(0x7F ,0x15);
|
||
writr_register(0x4C ,0x02);
|
||
writr_register(0x56 ,0x02);
|
||
writr_register(0x41 ,0x91);
|
||
writr_register(0x4D ,0x0A);
|
||
writr_register(0x7F ,0x0C);
|
||
writr_register(0x4A ,0x10);
|
||
writr_register(0x4B ,0x0C);
|
||
writr_register(0x4C ,0x40);
|
||
writr_register(0x41 ,0x25);
|
||
writr_register(0x55 ,0x18);
|
||
writr_register(0x56 ,0x14);
|
||
writr_register(0x49 ,0x0A);
|
||
writr_register(0x42 ,0x00);
|
||
writr_register(0x43 ,0x2D);
|
||
writr_register(0x44 ,0x0C);
|
||
writr_register(0x54 ,0x1A);
|
||
writr_register(0x5A ,0x0D);
|
||
writr_register(0x5F ,0x1E);
|
||
writr_register(0x5B ,0x05);
|
||
writr_register(0x5E ,0x0F);
|
||
writr_register(0x7F ,0x0D);
|
||
writr_register(0x48 ,0xDD);
|
||
writr_register(0x4F ,0x03);
|
||
writr_register(0x52 ,0x49);
|
||
|
||
writr_register(0x51 ,0x00);
|
||
writr_register(0x54 ,0x5B);
|
||
writr_register(0x53 ,0x00);
|
||
|
||
writr_register(0x56 ,0x64);
|
||
writr_register(0x55 ,0x00);
|
||
writr_register(0x58 ,0xA5);
|
||
writr_register(0x57 ,0x02);
|
||
writr_register(0x5A ,0x29);
|
||
writr_register(0x5B ,0x47);
|
||
writr_register(0x5C ,0x81);
|
||
writr_register(0x5D ,0x40);
|
||
writr_register(0x71 ,0xDC);
|
||
writr_register(0x70 ,0x07);
|
||
writr_register(0x73 ,0x00);
|
||
writr_register(0x72 ,0x08);
|
||
writr_register(0x75 ,0xDC);
|
||
writr_register(0x74 ,0x07);
|
||
writr_register(0x77 ,0x00);
|
||
writr_register(0x76 ,0x08);
|
||
writr_register(0x7F ,0x10);
|
||
writr_register(0x4C ,0xD0);
|
||
writr_register(0x7F ,0x00);
|
||
writr_register(0x4F ,0x63);
|
||
writr_register(0x4E ,0x00);
|
||
writr_register(0x52 ,0x63);
|
||
writr_register(0x51 ,0x00);
|
||
writr_register(0x54 ,0x54);
|
||
writr_register(0x5A ,0x10);
|
||
writr_register(0x77 ,0x4F);
|
||
writr_register(0x47 ,0x01);
|
||
writr_register(0x5B ,0x40);
|
||
writr_register(0x64 ,0x60);
|
||
writr_register(0x65 ,0x06);
|
||
writr_register(0x66 ,0x13);
|
||
writr_register(0x67 ,0x0F);
|
||
writr_register(0x78 ,0x01);
|
||
writr_register(0x79 ,0x9C);
|
||
writr_register(0x40 ,0x00);
|
||
writr_register(0x55 ,0x02);
|
||
writr_register(0x23 ,0x70);
|
||
writr_register(0x22 ,0x01);
|
||
|
||
//Wait for 1ms
|
||
delay_ms(1);
|
||
|
||
for( i = 0 ;i < 60 ;i++)
|
||
{
|
||
read_tmp = read_register(0x6C);
|
||
if(read_tmp == 0x80 )
|
||
break;
|
||
delay_ms(1);
|
||
}
|
||
if(i == 60)
|
||
{
|
||
writr_register(0x7F ,0x14);
|
||
writr_register(0x6C ,0x00);
|
||
writr_register(0x7F ,0x00);
|
||
}
|
||
writr_register(0x22 ,0x00);
|
||
writr_register(0x55 ,0x00);
|
||
writr_register(0x7F ,0x07);
|
||
writr_register(0x40 ,0x40);
|
||
writr_register(0x7F ,0x00);
|
||
}
|
||
|
||
/*
|
||
*RawData输出程序
|
||
* 读取当前鼠标摄像头拍摄到的接触面的像素阵列信息
|
||
* 像素信息存入数组pFrame中
|
||
*
|
||
*注意:
|
||
* 在RawData输出过程中,必须将鼠标置于静止位置
|
||
*
|
||
*/
|
||
void Pixel_Burst_Read(uint8_t* pFrame)
|
||
{
|
||
uint8_t reg_tmp;
|
||
//Lower NCS
|
||
CS_Low;
|
||
//Wait for t(NCS-SCLK)
|
||
delay_125_ns(PAW3395_TIMINGS_NCS_SCLK);
|
||
writr_register(0x7F ,0x00);
|
||
writr_register(0x40 ,0x80);
|
||
|
||
do
|
||
{
|
||
reg_tmp = read_register(PAW3395_SPIREGISTER_MOTION);
|
||
delay_us(PAW3395_TIMINGS_SRWSRR);
|
||
}
|
||
while((reg_tmp & ((1 << PAW3395_OP_MODE0) | (1 << PAW3395_OP_MODE1))) != 0);
|
||
|
||
writr_register(0x50 ,0x01);
|
||
writr_register(0x55 ,0x04);
|
||
writr_register(0x58 ,0xFF);
|
||
|
||
do
|
||
{
|
||
reg_tmp = read_register(0x59);
|
||
delay_us(PAW3395_TIMINGS_SRWSRR);
|
||
}
|
||
while((reg_tmp & ((1 << PAW3395_PG_FIRST) | (1 << PAW3395_PG_VALID)))
|
||
!= ((1 << PAW3395_PG_FIRST) | (1 << PAW3395_PG_VALID)));
|
||
|
||
pFrame[35*2]=read_register(0x58);//Read the first rawdata from register 0x58
|
||
delay_us(PAW3395_TIMINGS_SRWSRR);
|
||
for(uint8_t width = 0;width < 36;width++)
|
||
{
|
||
for(uint8_t height = 0;height < 36;height++)
|
||
{
|
||
if((width == 0)&&(height == 0))
|
||
continue;
|
||
do
|
||
{
|
||
reg_tmp = read_register(0x59);
|
||
delay_us(PAW3395_TIMINGS_SRWSRR);
|
||
}
|
||
while(!((reg_tmp >> PAW3395_PG_VALID) & 0x01));
|
||
pFrame[(height * 36 + (35-width)) * 2] = read_register(0x58);
|
||
delay_us(PAW3395_TIMINGS_SRWSRR);
|
||
}
|
||
}
|
||
|
||
writr_register(0x40 ,0x00);
|
||
writr_register(0x50 ,0x00);
|
||
writr_register(0x55 ,0x00);
|
||
CS_High;
|
||
delay_125_ns(PAW3395_TIMINGS_BEXIT);
|
||
}
|
||
|
||
|
||
/*
|
||
*
|
||
*更改DPI
|
||
*
|
||
*/
|
||
void DPI_Config(uint16_t CPI_Num)
|
||
{
|
||
uint8_t temp;
|
||
|
||
//Lower NCS
|
||
CS_Low;
|
||
//Wait for t(NCS-SCLK)
|
||
delay_125_ns(PAW3395_TIMINGS_NCS_SCLK);
|
||
|
||
//设置分辨率模式:X轴和Y轴分辨率均由RESOLUTION_X_LOW和RESOLUTION_X_HIGH定义
|
||
writr_register(MOTION_CTRL, 0x00);
|
||
|
||
//两个8位寄存器设置X轴分辨率
|
||
temp = (uint8_t)(((CPI_Num/50) << 8) >> 8);
|
||
writr_register(RESOLUTION_X_LOW, temp);
|
||
temp = (uint8_t)((CPI_Num/50) >> 8);
|
||
writr_register(RESOLUTION_X_HIGH, temp);
|
||
|
||
//更新分辨率
|
||
writr_register(SET_RESOLUTION, 0x01);
|
||
|
||
CS_High;
|
||
delay_125_ns(PAW3395_TIMINGS_BEXIT);
|
||
}
|