/*************************************************************************************************************
 * 文件名:			SC7A20.c
 * 功能:			SC7A20 三轴加速度传感器支持
 * 作者:			cp1300@139.com
 * 创建时间:		2022-07-01
 * 最后修改时间:	2022-07-01
 * 详细:			https://www.doc88.com/p-80659792307153.html?r=1
 *					如果想一次读写多个寄存器，需要将寄存器地址最高位置1，也就是寄存器地址|0x80
 *************************************************************************************************************/
#include "sr_sc7a20.h"

#include "sr_i2c.h"
#include "sr_log.h"
#include "sr_osal.h"

#include <math.h>

#define PI 3.1415926535898





SC7A20_DEV_T sc7a20Dev;


/*************************************************************************************************************************
*函数        	:	int SC7A20_Init(SC7A20_HANDLE *pHandle, uint8_t SlaveAddr,
                        int (*IIC_ReadReg)(uint8_t SlaveAddr, uint8_t RegAddr, uint8_t *pDataBuff, uint16_t ByteNum),
                        int (*IIC_WriteReg)(uint16_t SlaveAddr, uint8_t RegAddr, uint8_t *pDataBuff, uint16_t ByteNum))
*功能        	:	SC7A20初始化
*参数        	:	pHandle:句柄；SlaveAddr：芯片IIC写地址；IIC_ReadReg：IIC读取接口；IIC_WriteReg:IIC写入接口；
*返回        	:	0:初始化成功；-1:初始化失败
*依赖			: 	底层宏定义
*作者       		:	cp1300@139.com
*时间     		:	2022-07-01
*最后修改时间		:	2022-07-01
*说明        	:
*************************************************************************************************************************/
int SC7A20_Init(SC7A20_DEV_T *dev)
{
    uint8_t i,tempreg=0, chipId = 0;

    //I2C初始化
    dev->i2cDev = SR_HalI2cOpen(SC7A20_I2C_ID);
    if(!dev->i2cDev) return SR_EINIT;

    //读取芯片ID
    for (i = 0; i < 3; i++) // 重试3次
    {        
        if (SR_HalI2cReadReg(dev->i2cDev, SC7A20_ADDRESS, 0, SC7A20_REG_WHO_AM_I, &chipId, 1) != 0)
        {
            SR_LOG(INFO,"Sensor通讯失败\r\n");
        }
        else if (SC7A20_CHIP_ID == chipId)
        {
            break;
        }

        SR_OsDelay(100);
    }
    if(3 == i) return SR_FAIL;

    //Sensor寄存器初始化
    tempreg = 0x47;
    SR_HalI2cWriteReg(dev->i2cDev, SC7A20_ADDRESS, 0, SC7A20_REG_CTRL_1, &tempreg, 1); // 50Hz+正常模式xyz使能
    tempreg = 0x00;
    SR_HalI2cWriteReg(dev->i2cDev, SC7A20_ADDRESS, 0, SC7A20_REG_CTRL_2, &tempreg, 1); // 关闭滤波器，手册上面没有滤波器截止频率设置说明，开启后无法测量静止状态下的重力加速度
    tempreg = 0x00;
    SR_HalI2cWriteReg(dev->i2cDev, SC7A20_ADDRESS, 0, SC7A20_REG_CTRL_3, &tempreg, 1); // 关闭中断
    tempreg = 0x88;
    SR_HalI2cWriteReg(dev->i2cDev, SC7A20_ADDRESS, 0, SC7A20_REG_CTRL_4, &tempreg, 1); // 读取完成再更新，小端模式，2g+正常模式，高精度模式

    return 0;
}

int16_t SC7A20_12bitComplement(uint8_t msb, uint8_t lsb)
{
    int16_t temp;

    temp = msb << 8 | lsb;
    temp = temp >> 4; // 只有高12位有效
    temp = temp & 0x0fff;
    if (temp & 0x0800) // 负数 补码==>原码
    {
        temp = temp & 0x07ff; // 屏蔽最高位
        temp = ~temp;
        temp = temp + 1;
        temp = temp & 0x07ff;
        temp = -temp; // 还原最高位
    }
    return temp;
}

/*************************************************************************************************************************
 *函数        	:	int SC7A20_ReadAcceleration(SC7A20_HANDLE* pHandle, int16_t* pXa, int16_t* pYa, int16_t* pZa)
 *功能        	:	SC7A20读取加速度值
 *参数        	:	pHandle:句柄；pXa，pYa,pZa 三轴加速度值
 *返回        	:	0:成功；-1:失败
 *依赖			: 	底层宏定义
 *作者       		:	cp1300@139.com
 *时间     		:	2022-07-01
 *最后修改时间		:	2022-07-01
 *说明        	:
 *************************************************************************************************************************/
int SC7A20_ReadAcceleration(SC7A20_DEV_T *dev, int16_t *pXa, int16_t *pYa, int16_t *pZa)
{
    uint8_t buff[6]={0};
    uint8_t i;
    int16_t temp;
    
    if (SR_HalI2cReadReg(dev->i2cDev, SC7A20_ADDRESS, 0, SC7A20_REG_X_L | 0x80, buff, 6) != 0)
    {
        return SR_FAIL;
    }
    else
    {
        SR_HalI2cReadReg(dev->i2cDev, SC7A20_ADDRESS, 0, 0x27, &i, 1);

        // X轴
        *pXa = buff[1];
        *pXa <<= 8;
        *pXa |= buff[0];
        *pXa >>= 4; // 取12bit精度

        // Y轴
        *pYa = buff[3];
        *pYa <<= 8;
        *pYa |= buff[2];
        *pYa >>= 4; // 取12bit精度

        // Z轴
        *pZa = buff[5];
        *pZa <<= 8;
        *pZa |= buff[4];
        *pZa >>= 4; // 取12bit精度

        return 0;
    }
}


/*************************************************************************************************************************
 *函数        	:	int SC7A20_GetZAxisAngle(SC7A20_HANDLE* pHandle, int16_t AcceBuff[3], float* pAngleZ)
 *功能        	:	SC7A20 获取Z轴倾角
 *参数        	:	pHandle:句柄；AcceBuff:3个轴的加速度；pAngleZ：Z方向倾角
 *返回        	:	0:成功；-1:失败
 *依赖			: 	底层宏定义
 *作者       		:	cp1300@139.com
 *时间     		:	2022-07-02
 *最后修改时间		:	2022-07-02
 *说明        	:
 *************************************************************************************************************************/
int SC7A20_GetZAxisAngle(SC7A20_DEV_T *dev, int16_t AcceBuff[3], float *pAngleZ)
{
    double fx, fy, fz;
    double A;
    int16_t Xa, Ya, Za;

    if (SC7A20_ReadAcceleration(dev, &Xa, &Ya, &Za) != 0) return -1; // ADXL362 读取加速度数据
    // uart_printf("Xa:%d \tYa:%d \tZa:%d \r\n",Xa,Ya,Za);
    AcceBuff[0] = Xa; // x轴加速度
    AcceBuff[1] = Ya; // y轴加速度
    AcceBuff[2] = Za; // z轴加速度

    fx = Xa;
    fx *= 2.0 / 4096;
    fy = Ya;
    fy *= 2.0 / 4096;
    fz = Za;
    fz *= 2.0 / 4096;

    // uart_printf("fx：%.04f\tfy：%.04f\tfz：%.04f\t\r\n",fx,fy,fz);

    // Z方向
    A = fx * fx + fz * fz;
    A = sqrt(A);
    A = (double)A / fy;
    A = atan(A);
    A = A * 180 / PI;

    *pAngleZ = A;
    SR_LOG(INFO,"=======角度：%.04f\r\n", *pAngleZ);

    return 0;
}



static int _SensorOpen(SR_DEVICE_T *dev)
{
    SC7A20_DEV_T *sc7a20Dev = (SC7A20_DEV_T *)dev;

    //Sensor初始化
    return SC7A20_Init(sc7a20Dev);
}


static int _SensorClose(SR_DEVICE_T *dev)
{
    SC7A20_DEV_T *sc7a20Dev = (SC7A20_DEV_T *)dev;

    // 关闭接口
    return SR_HalI2cClose(sc7a20Dev->i2cDev);
}



static srSSize_t _SensorRead(SR_DEVICE_T *dev, srOff_t pos, void *buf, srSize_t len)
{
    int i,ret =-1;
    SC7A20_DEV_T *sc7a20Dev = (SC7A20_DEV_T *)dev;
    SR_SENSOR_DATA_T *data = (SR_SENSOR_DATA_T *)buf;

    for(i=0;i<len;i++)
    {
        ret =  SC7A20_ReadAcceleration(sc7a20Dev, (int16_t *)&data[i].data.acce.x, (int16_t *)&data[i].data.acce.y, (int16_t *)&data[i].data.acce.z);
        if(ret) break; 
        
        data[i].type = SR_SENSOR_TYPE_ACCE;
    }
      
    return (i>0)? i:SR_FAIL;
 
}


static int _SensorCtrl(SR_DEVICE_T *dev, int cmd, void *args)
{
    
    return  0;
}
    

static SR_DEVICE_OPS_T sensorOps = {
    .open    = _SensorOpen,
    .close   = _SensorClose,
    .read    = _SensorRead,
    .control = _SensorCtrl,
};


int SC7A20_Register(void)
{
    int ret;
    
    ret = SR_HalSensorRegister(&sc7a20Dev.sensor, "sc7a20", &sensorOps,SR_NULL);
    return ret;
}
SR_INIT_BSP_EXPORT(SC7A20_Register, SR_PRIORITY_2);
