/*********************************************************************************************************************
* 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_imu660ra
* ˾          ɶɿƼ޹˾
* 汾Ϣ          鿴 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_imu660ra.h  IMU660RA_SPC_PIN 궨
*                   SDA/DSI           鿴 zf_device_imu660ra.h  IMU660RA_SDI_PIN 궨
*                   SA0/SDO           鿴 zf_device_imu660ra.h  IMU660RA_SDO_PIN 궨
*                   CS                鿴 zf_device_imu660ra.h  IMU660RA_CS_PIN 궨
*                   VCC               3.3VԴ
*                   GND               Դ
*                   
*
*                   //  IIC 
*                   SCL/SPC           鿴 zf_device_imu660ra.h  IMU660RA_SCL_PIN 궨
*                   SDA/DSI           鿴 zf_device_imu660ra.h  IMU660RA_SDA_PIN 궨
*                   VCC               3.3VԴ
*                   GND               Դ
*                   
*                   ------------------------------------
********************************************************************************************************************/

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

#include "zf_device_imu660ra.h"

int16 imu660ra_gyro_x = 0, imu660ra_gyro_y = 0, imu660ra_gyro_z = 0;            //       GYRO ()
int16 imu660ra_acc_x = 0, imu660ra_acc_y = 0, imu660ra_acc_z = 0;               // ٶȼ     ACC  (accelerometer ٶȼ)
float imu660ra_transition_factor[2] = {4096, 16.4};                             // תʵֵı

#if IMU660RA_USE_SOFT_IIC
static soft_iic_info_struct imu660ra_iic_struct;

#define imu660ra_write_register(reg, data)        (soft_iic_write_8bit_register (&imu660ra_iic_struct, (reg), (data)))
#define imu660ra_write_registers(reg, data, len)  (soft_iic_write_8bit_registers(&imu660ra_iic_struct, (reg), (data), (len)))
#define imu660ra_read_register(reg)               (soft_iic_read_8bit_register  (&imu660ra_iic_struct, (reg)))
#define imu660ra_read_registers(reg, data, len)   (soft_iic_read_8bit_registers (&imu660ra_iic_struct, (reg), (data), (len)))
#else
//-------------------------------------------------------------------------------------------------------------------
//      IMU660RA дĴ
// ˵     reg             Ĵַ
// ˵     data            
// ز     void
// ʹʾ     imu660ra_write_register(IMU660RA_PWR_CONF, 0x00);                   // رո߼ʡģʽ
// עϢ     ڲ
//-------------------------------------------------------------------------------------------------------------------
static void imu660ra_write_register(uint8 reg, uint8 data)
{
    IMU660RA_CS(0);
    spi_write_8bit_register(IMU660RA_SPI, reg | IMU660RA_SPI_W, data);
    IMU660RA_CS(1);
}

//-------------------------------------------------------------------------------------------------------------------
//      IMU660RA д
// ˵     reg             Ĵַ
// ˵     data            
// ز     void
// ʹʾ     imu660ra_write_registers(IMU660RA_INIT_DATA, imu660ra_config_file, sizeof(imu660ra_config_file));
// עϢ     ڲ
//-------------------------------------------------------------------------------------------------------------------
static void imu660ra_write_registers(uint8 reg, const uint8 *data, uint32 len)
{
    IMU660RA_CS(0);
    spi_write_8bit_registers(IMU660RA_SPI, reg | IMU660RA_SPI_W, data, len);
    IMU660RA_CS(1);
}

//-------------------------------------------------------------------------------------------------------------------
//      IMU660RA Ĵ
// ˵     reg             Ĵַ
// ز     uint8           
// ʹʾ     imu660ra_read_register(IMU660RA_CHIP_ID);
// עϢ     ڲ
//-------------------------------------------------------------------------------------------------------------------
static uint8 imu660ra_read_register(uint8 reg)
{
    uint8 data[2];
    IMU660RA_CS(0);
    spi_read_8bit_registers(IMU660RA_SPI, reg | IMU660RA_SPI_R, data, 2);
    IMU660RA_CS(1);
    return data[1];
}

//-------------------------------------------------------------------------------------------------------------------
//      IMU660RA 
// ˵     reg             Ĵַ
// ˵     data            ݻ
// ˵     len             ݳ
// ز     void
// ʹʾ     imu660ra_read_registers(IMU660RA_ACC_ADDRESS, dat, 6);
// עϢ     ڲ
//-------------------------------------------------------------------------------------------------------------------
static void imu660ra_read_registers(uint8 reg, uint8 *data, uint32 len)
{
    uint8 temp_data[8];
    IMU660RA_CS(0);
    spi_read_8bit_registers(IMU660RA_SPI, reg | IMU660RA_SPI_R, temp_data, len + 1);
    IMU660RA_CS(1);
    for(int i = 0; i < len; i ++)
    {
        *(data ++) = temp_data[i + 1];
    }
}
#endif

//-------------------------------------------------------------------------------------------------------------------
//      IMU660RA Լ
// ˵     void
// ز     uint8           1-Լʧ 0-Լɹ
// ʹʾ     imu660ra_self_check();
// עϢ     ڲ
//-------------------------------------------------------------------------------------------------------------------
static uint8 imu660ra_self_check (void)
{
    uint8 dat = 0, return_state = 0;
    uint16 timeout_count = 0;
    do
    {
        if(IMU660RA_TIMEOUT_COUNT < timeout_count ++)
        {
            return_state =  1;
            break;
        }
        dat = imu660ra_read_register(IMU660RA_CHIP_ID);
        system_delay_ms(1);
    }while(0x24 != dat);                                                    // ȡ豸IDǷ0X240X24Ϊû⵽豸
    return return_state;
}

//-------------------------------------------------------------------------------------------------------------------
//      ȡ IMU660RA ٶȼ
// ˵     void
// ز     void
// ʹʾ     imu660ra_get_acc();                                             // ִиúֱӲ鿴Ӧı
// עϢ     ʹ SPI ĲɼʱΪ69us
//            ʹ IIC ĲɼʱΪ126us        ɼٶȼƵʱɼǵʱһµԭǶֻǶȡĴ
//-------------------------------------------------------------------------------------------------------------------
void imu660ra_get_acc (void)
{
    uint8 dat[6];

    imu660ra_read_registers(IMU660RA_ACC_ADDRESS, dat, 6);
    imu660ra_acc_x = (int16)(((uint16)dat[1]<<8 | dat[0]));
    imu660ra_acc_y = (int16)(((uint16)dat[3]<<8 | dat[2]));
    imu660ra_acc_z = (int16)(((uint16)dat[5]<<8 | dat[4]));
}
//-------------------------------------------------------------------------------------------------------------------
//      ȡ IMU660RA 
// ˵     void
// ز     void
// ʹʾ     imu660ra_get_gyro();                                            // ִиúֱӲ鿴Ӧı
// עϢ     ʹ SPI ĲɼʱΪ69us
//            ʹ IIC ĲɼʱΪ126us
//-------------------------------------------------------------------------------------------------------------------
void imu660ra_get_gyro (void)
{
    uint8 dat[6];

    imu660ra_read_registers(IMU660RA_GYRO_ADDRESS, dat, 6);
    imu660ra_gyro_x = (int16)(((uint16)dat[1]<<8 | dat[0]));
    imu660ra_gyro_y = (int16)(((uint16)dat[3]<<8 | dat[2]));
    imu660ra_gyro_z = (int16)(((uint16)dat[5]<<8 | dat[4]));
}

//-------------------------------------------------------------------------------------------------------------------
//      ʼ IMU660RA
// ˵     void
// ز     uint8           1-ʼʧ 0-ʼɹ
// ʹʾ     imu660ra_init();
// עϢ
//-------------------------------------------------------------------------------------------------------------------
uint8 imu660ra_init (void)
{
    uint8 return_state = 0;
    system_delay_ms(20);                                                    // ȴ豸ϵɹ
#if IMU660RA_USE_SOFT_IIC
    soft_iic_init(&imu660ra_iic_struct, IMU660RA_DEV_ADDR, IMU660RA_SOFT_IIC_DELAY, IMU660RA_SCL_PIN, IMU660RA_SDA_PIN);        //  IMU660RA  IIC˿
#else
    spi_init(IMU660RA_SPI, SPI_MODE0, IMU660RA_SPI_SPEED, IMU660RA_SPC_PIN, IMU660RA_SDI_PIN, IMU660RA_SDO_PIN, SPI_CS_NULL);   //  IMU660RA  SPI˿
    gpio_init(IMU660RA_CS_PIN, GPO, GPIO_HIGH, GPO_PUSH_PULL);                                                                  //  IMU660RA  CS˿
    imu660ra_read_register(IMU660RA_CHIP_ID);                                                                                   // ȡһ豸ID豸ΪSPIģʽ
#endif
    do{
        if(imu660ra_self_check())                                           // IMU660RAԼ
        {
            // ˶Ϣ ʾλ
            // ô imu660ra Լʱ˳
            // һ½û ûܾǻ
            zf_log(0, "imu660ra self check error.");
            return_state = 1;
            break;
        }
        imu660ra_write_register(IMU660RA_PWR_CONF, 0x00);                       // رո߼ʡģʽ
        system_delay_ms(1);
        imu660ra_write_register(IMU660RA_INIT_CTRL, 0x00);                      // ʼģгʼ
        imu660ra_write_registers(IMU660RA_INIT_DATA, imu660ra_config_file, sizeof(imu660ra_config_file));                       // ļ
        imu660ra_write_register(IMU660RA_INIT_CTRL, 0x01);                      // ʼý
        system_delay_ms(20);
        if(1 != imu660ra_read_register(IMU660RA_INT_STA))                       // Ƿ
        {
            // ˶Ϣ ʾλ
            // ô imu660ra óʼļ
            // һ½û ûܾǻ
            zf_log(0, "imu660ra init error.");
            return_state = 1;
            break;
        }
        imu660ra_write_register(IMU660RA_PWR_CTRL, 0x0E);                       // ģʽ  ʹǡٶȡ¶ȴ
        imu660ra_write_register(IMU660RA_ACC_CONF, 0xA7);                       // ٶȲɼ ģʽ ɼ 50Hz  Ƶ
        imu660ra_write_register(IMU660RA_GYR_CONF, 0xA9);                       // ǲɼ ģʽ ɼ 200Hz Ƶ

        // IMU660RA_GYR_SAMPLEĴ
        // Ϊ:0x00 Ϊ:2000dps      ȡݳ16.4          תΪλݣλΪ/s
        // Ϊ:0x01 Ϊ:1000dps      ȡݳ32.8          תΪλݣλΪ/s
        // Ϊ:0x02 Ϊ:500 dps      ȡݳ65.6          תΪλݣλΪ/s
        // Ϊ:0x03 Ϊ:250 dps      ȡݳ131.2         תΪλݣλΪ/s
        switch(IMU660RA_ACC_SAMPLE_DEFAULT)
        {
            case IMU660RA_ACC_SAMPLE_SGN_2G:
            {
                imu660ra_write_register(IMU660RA_ACC_RANGE, 0x00);
                imu660ra_transition_factor[0] = 16384;
            }break;
            case IMU660RA_ACC_SAMPLE_SGN_4G:
            {
                imu660ra_write_register(IMU660RA_ACC_RANGE, 0x01);
                imu660ra_transition_factor[0] = 8192;
            }break;
            case IMU660RA_ACC_SAMPLE_SGN_8G:
            {
                imu660ra_write_register(IMU660RA_ACC_RANGE, 0x02);
                imu660ra_transition_factor[0] = 4096;
            }break;
            case IMU660RA_ACC_SAMPLE_SGN_16G:
            {
                imu660ra_write_register(IMU660RA_ACC_RANGE, 0x03);
                imu660ra_transition_factor[0] = 2048;
            }break;
            default:
            {
                zf_log(0, "IMU660RA_ACC_SAMPLE_DEFAULT set error.");
                return_state = 1;
            }break;
        }
        if(1 == return_state)
        {
            break;
        }

        // IMU660RA_ACC_SAMPLEĴ
        // Ϊ:0x00 ٶȼΪ:2g          ȡļٶȼ 16384      תΪλݣλg(m/s^2)
        // Ϊ:0x01 ٶȼΪ:4g          ȡļٶȼ 8192       תΪλݣλg(m/s^2)
        // Ϊ:0x02 ٶȼΪ:8g          ȡļٶȼ 4096       תΪλݣλg(m/s^2)
        // Ϊ:0x03 ٶȼΪ:16g         ȡļٶȼ 2048       תΪλݣλg(m/s^2)
        switch(IMU660RA_GYRO_SAMPLE_DEFAULT)
        {
            case IMU660RA_GYRO_SAMPLE_SGN_125DPS:
            {
                imu660ra_write_register(IMU660RA_GYR_RANGE, 0x04);
                imu660ra_transition_factor[1] = 262.4;
            }break;
            case IMU660RA_GYRO_SAMPLE_SGN_250DPS:
            {
                imu660ra_write_register(IMU660RA_GYR_RANGE, 0x03);
                imu660ra_transition_factor[1] = 131.2;
            }break;
            case IMU660RA_GYRO_SAMPLE_SGN_500DPS:
            {
                imu660ra_write_register(IMU660RA_GYR_RANGE, 0x02);
                imu660ra_transition_factor[1] = 65.6;
            }break;
            case IMU660RA_GYRO_SAMPLE_SGN_1000DPS:
            {
                imu660ra_write_register(IMU660RA_GYR_RANGE, 0x01);
                imu660ra_transition_factor[1] = 32.8;
            }break;
            case IMU660RA_GYRO_SAMPLE_SGN_2000DPS:
            {
                imu660ra_write_register(IMU660RA_GYR_RANGE, 0x00);
                imu660ra_transition_factor[1] = 16.4;
            }break;
            default:
            {
                zf_log(0, "IMU660RA_GYRO_SAMPLE_DEFAULT set error.");
                return_state = 1;
            }break;
        }
        if(1 == return_state)
        {
            break;
        }
    }while(0);
    return return_state;
}


