/*********************************************************************************************************************
* TC264 Opensourec Library TC264 Դ⣩һڹٷ SDK ӿڵĵԴ
* Copyright (c) 2022 SEEKFREE ɿƼ
*
* ļ TC264 Դһ
*
* TC264 Դ 
* Ըᷢ GPLGNU General Public License GNUͨù֤
*  GPL ĵ3棨 GPL3.0ѡģκκİ汾·/޸
*
* Դķϣܷãδκεı֤
* ûԻʺض;ı֤
* ϸμ GPL
*
* ӦյԴͬʱյһ GPL ĸ
* ûУ<https://www.gnu.org/licenses/>
*
* ע
* Դʹ GPL3.0 Դ֤Э Ϊİ汾
* Ӣİ libraries/doc ļµ GPL3_permission_statement.txt ļ
* ֤ libraries ļ ļµ LICENSE ļ
* ӭλʹò ޸ʱ뱣ɿƼİȨ
*
* ļ          zf_device_icm20602
* ˾          ɶɿƼ޹˾
* 汾Ϣ          鿴 libraries/doc ļ version ļ 汾˵
*           ADS v1.9.4
* ƽ̨          TC264D
*           https://seekfree.taobao.com/
*
* ޸ļ¼
*                              ע
* 2022-09-15       pudding            first version
* 2023-04-28       pudding            ע˵
********************************************************************************************************************/
/*********************************************************************************************************************
* ߶壺
*                   ------------------------------------
*                   ģܽ           Ƭܽ
*                   // Ӳ SPI 
*                   SCL/SPC           鿴 zf_device_icm20602.h  ICM20602_SPC_PIN 궨
*                   SDA/DSI           鿴 zf_device_icm20602.h  ICM20602_SDI_PIN 궨
*                   SA0/SDO           鿴 zf_device_icm20602.h  ICM20602_SDO_PIN 궨
*                   CS                鿴 zf_device_icm20602.h  ICM20602_CS_PIN 궨
*                   VCC               3.3VԴ
*                   GND               Դ
*                   
*
*                   //  IIC 
*                   SCL/SPC           鿴 zf_device_icm20602.h  ICM20602_SCL_PIN 궨
*                   SDA/DSI           鿴 zf_device_icm20602.h  ICM20602_SDA_PIN 궨
*                   VCC               3.3VԴ
*                   GND               Դ
*                   
*                   ------------------------------------
********************************************************************************************************************/

#include "zf_common_debug.h"
#include "zf_driver_delay.h"
#include "zf_driver_spi.h"
#include "zf_driver_gpio.h"
#include "zf_driver_soft_iic.h"
#include "zf_device_icm20602.h"

int16 icm20602_gyro_x = 0, icm20602_gyro_y = 0, icm20602_gyro_z = 0;            //       gyro ()
int16 icm20602_acc_x = 0, icm20602_acc_y = 0, icm20602_acc_z = 0;               // ٶȼ    acc (accelerometer ٶȼ)
float icm20602_transition_factor[2] = {4096, 16.4};                             // תʵֵı

#if ICM20602_USE_SOFT_IIC
static soft_iic_info_struct icm20602_iic_struct;

//-------------------------------------------------------------------------------------------------------------------
//      ICM20602 дĴ
// ˵     reg             Ĵַ
// ˵     data            
// ز     void
// ʹʾ     icm20602_write_register(ICM20602_PWR_MGMT_1, 0x80);
// עϢ     ڲ
//-------------------------------------------------------------------------------------------------------------------
#define icm20602_write_register(reg, data)      (soft_iic_write_8bit_register(&icm20602_iic_struct, (reg), (data)))

//-------------------------------------------------------------------------------------------------------------------
//      ICM20602 Ĵ
// ˵     reg             Ĵַ
// ز     uint8           
// ʹʾ     icm20602_read_register(ICM20602_WHO_AM_I);
// עϢ     ڲ
//-------------------------------------------------------------------------------------------------------------------
#define icm20602_read_register(reg)             (soft_iic_read_8bit_register(&icm20602_iic_struct, (reg)))

//-------------------------------------------------------------------------------------------------------------------
//      ICM20602 
// ˵     reg             Ĵַ
// ˵     data            ݻ
// ˵     len             ݳ
// ز     void
// ʹʾ     icm20602_read_registers(ICM20602_ACCEL_XOUT_H, dat, 6);
// עϢ     ڲ
//-------------------------------------------------------------------------------------------------------------------
#define icm20602_read_registers(reg, data, len) (soft_iic_read_8bit_registers(&icm20602_iic_struct, (reg), (data), (len)))
#else
//-------------------------------------------------------------------------------------------------------------------
//      ICM20602 дĴ
// ˵     reg             Ĵַ
// ˵     data            
// ز     void
// ʹʾ     icm20602_write_register(ICM20602_PWR_MGMT_1, 0x80);
// עϢ     ڲ
//-------------------------------------------------------------------------------------------------------------------
static void icm20602_write_register(uint8 reg, uint8 data)
{
    ICM20602_CS(0);
    spi_write_8bit_register(ICM20602_SPI, reg | ICM20602_SPI_W, data);
    ICM20602_CS(1);
}

//-------------------------------------------------------------------------------------------------------------------
//      ICM20602 Ĵ
// ˵     reg             Ĵַ
// ز     uint8           
// ʹʾ     icm20602_read_register(ICM20602_WHO_AM_I);
// עϢ     ڲ
//-------------------------------------------------------------------------------------------------------------------
static uint8 icm20602_read_register(uint8 reg)
{
    uint8 data = 0;
    ICM20602_CS(0);
    data = spi_read_8bit_register(ICM20602_SPI, reg | ICM20602_SPI_R);
    ICM20602_CS(1);
    return data;
}

//-------------------------------------------------------------------------------------------------------------------
//      ICM20602 
// ˵     reg             Ĵַ
// ˵     data            ݻ
// ˵     len             ݳ
// ز     void
// ʹʾ     icm20602_read_registers(ICM20602_ACCEL_XOUT_H, dat, 6);
// עϢ     ڲ
//-------------------------------------------------------------------------------------------------------------------
static void icm20602_read_registers(uint8 reg, uint8 *data, uint32 len)
{
    ICM20602_CS(0);
    spi_read_8bit_registers(ICM20602_SPI, reg | ICM20602_SPI_R, data, len);
    ICM20602_CS(1);
}
#endif

//-------------------------------------------------------------------------------------------------------------------
//      ICM20602 Լ
// ˵     void
// ز     uint8           1-Լʧ 0-Լɹ
// ʹʾ     icm20602_self_check();
// עϢ     ڲ
//-------------------------------------------------------------------------------------------------------------------
static uint8 icm20602_self_check (void)
{
    uint8 dat = 0, return_state = 0;
    uint16 timeout_count = 0;

    while(0x12 != dat)                                                          // ж ID Ƿȷ
    {
        if(ICM20602_TIMEOUT_COUNT < timeout_count ++)
        {
            return_state =  1;
            break;
        }
        dat = icm20602_read_register(ICM20602_WHO_AM_I);
        system_delay_ms(10);
    }
    return return_state;
}

//-------------------------------------------------------------------------------------------------------------------
//      ȡ ICM20602 ٶȼ
// ˵     void
// ز     void
// ʹʾ     icm20602_get_acc();                                             // ִиúֱӲ鿴Ӧı
// עϢ
//-------------------------------------------------------------------------------------------------------------------
void icm20602_get_acc (void)
{
    uint8 dat[6];

    icm20602_read_registers(ICM20602_ACCEL_XOUT_H, dat, 6);
    icm20602_acc_x = (int16)(((uint16)dat[0] << 8 | dat[1]));
    icm20602_acc_y = (int16)(((uint16)dat[2] << 8 | dat[3]));
    icm20602_acc_z = (int16)(((uint16)dat[4] << 8 | dat[5]));
}

//-------------------------------------------------------------------------------------------------------------------
//      ȡ ICM20602 
// ˵     void
// ز     void
// ʹʾ     icm20602_get_gyro();                                            // ִиúֱӲ鿴Ӧı
// עϢ
//-------------------------------------------------------------------------------------------------------------------
void icm20602_get_gyro (void)
{
    uint8 dat[6];

    icm20602_read_registers(ICM20602_GYRO_XOUT_H, dat, 6);
    icm20602_gyro_x = (int16)(((uint16)dat[0] << 8 | dat[1]));
    icm20602_gyro_y = (int16)(((uint16)dat[2] << 8 | dat[3]));
    icm20602_gyro_z = (int16)(((uint16)dat[4] << 8 | dat[5]));
}

//-------------------------------------------------------------------------------------------------------------------
//      ʼ ICM20602
// ˵     void
// ز     uint8           1-ʼʧ 0-ʼɹ
// ʹʾ     icm20602_init();
// עϢ
//-------------------------------------------------------------------------------------------------------------------
uint8 icm20602_init (void)
{
    uint8 val = 0x0, return_state = 0;
    uint16 timeout_count = 0;

    system_delay_ms(10);                                                        // ϵʱ

#if ICM20602_USE_SOFT_IIC
    soft_iic_init(&icm20602_iic_struct, ICM20602_DEV_ADDR, ICM20602_SOFT_IIC_DELAY, ICM20602_SCL_PIN, ICM20602_SDA_PIN);
#else
    spi_init(ICM20602_SPI, SPI_MODE0, ICM20602_SPI_SPEED, ICM20602_SPC_PIN, ICM20602_SDI_PIN, ICM20602_SDO_PIN, SPI_CS_NULL);
    gpio_init(ICM20602_CS_PIN, GPO, GPIO_HIGH, GPO_PUSH_PULL);
#endif

    do
    {
        if(icm20602_self_check())
        {
            // ˶Ϣ ʾλ
            // ô ICM20602 Լʱ˳
            // һ½û ûܾǻ
            zf_log(0, "icm20602 self check error.");
            return_state = 1;
            break;
        }

        icm20602_write_register(ICM20602_PWR_MGMT_1, 0x80);                     // λ豸
        system_delay_ms(2);

        do
        {                                                                       // ȴλɹ
            val = icm20602_read_register(ICM20602_PWR_MGMT_1);
            if(ICM20602_TIMEOUT_COUNT < timeout_count ++)
            {
                // ˶Ϣ ʾλ
                // ô ICM20602 Լʱ˳
                // һ½û ûܾǻ
                zf_log(0, "icm20602 reset error.");
                return_state = 1;
                break;
            }
        }while(0x41 != val);
        if(1 == return_state)
        {
            break;
        }

        icm20602_write_register(ICM20602_PWR_MGMT_1,     0x01);                 // ʱ
        icm20602_write_register(ICM20602_PWR_MGMT_2,     0x00);                 // Ǻͼٶȼ
        icm20602_write_register(ICM20602_CONFIG,         0x01);                 // 176HZ 1KHZ
        icm20602_write_register(ICM20602_SMPLRT_DIV,     0x07);                 //  SAMPLE_RATE = INTERNAL_SAMPLE_RATE / (1 + SMPLRT_DIV)

        // ICM20602_ACCEL_CONFIG Ĵ
        // Ϊ 0x00 ٶȼΪ 2  g   ȡļٶȼݳ 16384  תΪλ λ g(m/s^2)
        // Ϊ 0x08 ٶȼΪ 4  g   ȡļٶȼݳ 8192   תΪλ λ g(m/s^2)
        // Ϊ 0x10 ٶȼΪ 8  g   ȡļٶȼݳ 4096   תΪλ λ g(m/s^2)
        // Ϊ 0x18 ٶȼΪ 16 g   ȡļٶȼݳ 2048   תΪλ λ g(m/s^2)
        switch(ICM20602_ACC_SAMPLE_DEFAULT)
        {
            case ICM20602_ACC_SAMPLE_SGN_2G:
            {
                icm20602_write_register(ICM20602_ACCEL_CONFIG, 0x00);
                icm20602_transition_factor[0] = 16384;
            }break;
            case ICM20602_ACC_SAMPLE_SGN_4G:
            {
                icm20602_write_register(ICM20602_ACCEL_CONFIG, 0x08);
                icm20602_transition_factor[0] = 8192;
            }break;
            case ICM20602_ACC_SAMPLE_SGN_8G:
            {
                icm20602_write_register(ICM20602_ACCEL_CONFIG, 0x10);
                icm20602_transition_factor[0] = 4096;
            }break;
            case ICM20602_ACC_SAMPLE_SGN_16G:
            {
                icm20602_write_register(ICM20602_ACCEL_CONFIG, 0x18);
                icm20602_transition_factor[0] = 2048;
            }break;
            default:
            {
                zf_log(0, "ICM20602_ACC_SAMPLE_DEFAULT set error.");
                return_state = 1;
            }break;
        }
        if(1 == return_state)
        {
            break;
        }

        // ICM20602_GYRO_CONFIG Ĵ
        // Ϊ 0x00 Ϊ 250  dps    ȡݳ 131     תΪλ λΪ /s
        // Ϊ 0x08 Ϊ 500  dps    ȡݳ 65.5    תΪλ λΪ /s
        // Ϊ 0x10 Ϊ 1000 dps    ȡݳ 32.8    תΪλ λΪ /s
        // Ϊ 0x18 Ϊ 2000 dps    ȡݳ 16.4    תΪλ λΪ /s
        switch(ICM20602_GYRO_SAMPLE_DEFAULT)
        {
            case ICM20602_GYRO_SAMPLE_SGN_250DPS:
            {
                icm20602_write_register(ICM20602_GYRO_CONFIG, 0x00);
                icm20602_transition_factor[1] = 131.0;
            }break;
            case ICM20602_GYRO_SAMPLE_SGN_500DPS:
            {
                icm20602_write_register(ICM20602_GYRO_CONFIG, 0x08);
                icm20602_transition_factor[1] = 65.5;
            }break;
            case ICM20602_GYRO_SAMPLE_SGN_1000DPS:
            {
                icm20602_write_register(ICM20602_GYRO_CONFIG, 0x10);
                icm20602_transition_factor[1] = 32.8;
            }break;
            case ICM20602_GYRO_SAMPLE_SGN_2000DPS:
            {
                icm20602_write_register(ICM20602_GYRO_CONFIG, 0x18);
                icm20602_transition_factor[1] = 16.4;
            }break;
            default:
            {
                zf_log(0, "ICM20602_GYRO_SAMPLE_DEFAULT set error.");
                return_state = 1;
            }break;
        }
        if(1 == return_state)
        {
            break;
        }

        icm20602_write_register(ICM20602_ACCEL_CONFIG_2, 0x03);                 // Average 4 samples   44.8HZ   //0x23 Average 16 samples
    }while(0);
    return return_state;
}
