// i2c_ads1115.c
#include "i2c_ads1115.h"
#include "stdlib.h"
#include "stdio.h"
#include "elog.h"

/*
    多路测量的话, 需要配置不同的 config_H  config_L
*/

static I2C_HandleTypeDef *pADS1115_I2C = &hi2c1;

osThreadId_t ads1115TaskHandle;
const osThreadAttr_t ads1115Task_attributes = {
    .name = "ads1115Task",
    .stack_size = 256 * 4,
    .priority = (osPriority_t) osPriorityNormal,
};

osEventFlagsId_t ads1115EventHandle;
const osEventFlagsAttr_t ads1115Event_attributes = {
    .name = "ads1115Event",
};

// ads1115EventHandle = osEventFlagsNew (&ads1115Event_attributes);
//  typedef enum
// {
//     EV_READY,                   /*!< Startup finished. */
//     EV_FRAME_RECEIVED,          /*!< Frame received. */
//     EV_EXECUTE,                 /*!< Execute function. */
//     EV_FRAME_SENT               /*!< Frame sent. */
// } eMBEventType;
// osEventFlagsSet(modbusEventHandle,eEvent);
    // osEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags)
// recvedEvent = osEventFlagsWait (modbusEventHandle,
//                                     EV_READY | EV_FRAME_RECEIVED | EV_EXECUTE |
//                                         EV_FRAME_SENT, /* 接收任务感兴趣的事件                                                       */
//                                     0,  
//                                     portMAX_DELAY); /* 指定超时事件,无限等待 */

ADS1115_TypeDef my_ads1115 =
    {
        ads1115_init,
        ads1115_port,
        ads1115_test,
        ads1115_start,
        ads1115_stop,
        NULL,
        ADS1115_REG_CONFIG_OS_START,
        ADS1115_REG_CONFIG_MUX_SINGLE_0,
        ADS1115_REG_CONFIG_PGA_4,
        ADS1115_REG_CONFIG_MODE_SINGLE,
        ADS1115_REG_CONFIG_DR_128,
        ADS1115_REG_CONFIG_COMP_MODE_TRADITIONAL,
        ADS1115_REG_CONFIG_COMP_POL_LOW,
        ADS1115_REG_CONFIG_COMP_LAT_NONLATCH,
        ADS1115_REG_CONFIG_COMP_QUE_DIS,
        0,              // point addr
        0,              // config_H
        0,              // config_L
        { 0, 0, 0 },    //  reg_data[3]
        ADS1115_OUTPUT_UNIT_mv,  // 默认输出毫伏
        0,    // event_flags 
        0,    // state
        {0,0},    // result
};

void ads1115_task(void)
{
    uint8_t event_flags;
    uint8_t reg_data[3] ={0}; 
    for (;;)
    {
        switch ( my_ads1115.state )
        {
        case ADS1115_WORK_STATE_WAITING:
            osDelay(20);
            break;

        //  Init    
        case ADS1115_WORK_STATE_INIT:
            // log_i("ads1115 init ....   %d  ",  osEventFlagsGet( ads1115EventHandle));

            if ( osEventFlagsGet( ads1115EventHandle) == 0 )
            {
                osEventFlagsSet( ads1115EventHandle, ADS1115_Event_INIT );

                my_ads1115.reg_data[0] = 0x01;                 //  point addr  8bit  配置寄存器
                my_ads1115.reg_data[1] = my_ads1115.config_H;  //  config_reg 高位
                my_ads1115.time_ticks =  osKernelGetTickCount( );
                if ( HAL_I2C_Master_Transmit_IT( pADS1115_I2C, ADS1115_WRITE_ADDRESS, my_ads1115.reg_data, 3 ) != HAL_OK)
                {
                    // log_e( "ads1115 set register failure while reading!!!" );
                    my_ads1115.state  ==  ADS1115_WORK_STATE_ERROR ;
                }                
            }
            if ( (osKernelGetTickCount() - my_ads1115.time_ticks) > 5 *1000)
            {
                my_ads1115.state  ==  ADS1115_WORK_STATE_TIMEOUT ;
            }
            break;     
        case ADS1115_WORK_STATE_INIT_SUCCESS:
            // log_i("ads1115 init success ... " );
            osEventFlagsClear( ads1115EventHandle, ADS1115_Event_INIT );
            osEventFlagsSet( ads1115EventHandle, ADS1115_Event_READY );
            break; 

        //  SET REGISTER   
        case ADS1115_WORK_STATE_SET_REGISTER:
            // log_i("ads1115 set register ....   %d  ",  osEventFlagsGet( ads1115EventHandle));

            if ( osEventFlagsGet( ads1115EventHandle) == 0  )
            {
                osEventFlagsSet( ads1115EventHandle, ADS1115_Event_SET_REGISTER );

                my_ads1115.reg_data[0] = 0x01;                 //  point addr  8bit  配置寄存器
                my_ads1115.reg_data[1] = my_ads1115.config_H;  //  config_reg 高位
                my_ads1115.time_ticks =  osKernelGetTickCount( );
                if ( HAL_I2C_Master_Transmit_IT( pADS1115_I2C, ADS1115_WRITE_ADDRESS, my_ads1115.reg_data, 3 ) != HAL_OK)
                {
                    // log_e("ads1115 set register failure while reading!!!");
                    my_ads1115.state  =  ADS1115_WORK_STATE_ERROR ;
                }
            }
            if ( (osKernelGetTickCount() - my_ads1115.time_ticks) > 5 *1000)
            {
                my_ads1115.state  =   ADS1115_WORK_STATE_TIMEOUT ;
            }
            break;   
        case ADS1115_WORK_STATE_SET_REGISTER_SUCCESS:
            // log_e("ads1115 set register.....succ");
            osEventFlagsClear( ads1115EventHandle, ADS1115_Event_SET_REGISTER );
            osEventFlagsSet( ads1115EventHandle, ADS1115_Event_READY  );
            my_ads1115.state  =   ADS1115_WORK_STATE_SET_POINT_ADDR ;
            break;   

        //  SET POINT ADDR   
        case ADS1115_WORK_STATE_SET_POINT_ADDR:
            // log_i("ads1115 set point addr ....   %d  ",  osEventFlagsGet( ads1115EventHandle));
            if ( osEventFlagsGet( ads1115EventHandle) == 0  )
            {
                osEventFlagsSet( ads1115EventHandle, ADS1115_Event_SET_POINT_ADDR );
                my_ads1115.time_ticks =  osKernelGetTickCount( );
                if ( HAL_I2C_Master_Transmit_IT(pADS1115_I2C, ADS1115_WRITE_ADDRESS, 0x00, 1 ) != HAL_OK )
                {
                    // log_e("ads1115 set register failure while reading!!!");
                    my_ads1115.state  =   ADS1115_WORK_STATE_ERROR ;
                }
            }
            if ( (osKernelGetTickCount() - my_ads1115.time_ticks) > 5 *1000 )
            {
                my_ads1115.state  =  ADS1115_WORK_STATE_TIMEOUT ;
            }
            break;   
        case ADS1115_WORK_STATE_SET_POINT_ADDR_SUCCESS:
            // log_e("ads1115 set point addr.....succ");
            osEventFlagsClear( ads1115EventHandle, ADS1115_Event_SET_POINT_ADDR );
            osEventFlagsSet( ads1115EventHandle, ADS1115_Event_READY  );
            my_ads1115.state  =   ADS1115_WORK_STATE_RCV_DATA ;
            break;  

        //  RCV DATA   
        case ADS1115_WORK_STATE_RCV_DATA:
            // log_i("ads1115 rcv data ....   %d  ",  osEventFlagsGet( ads1115EventHandle));
            if ( osEventFlagsGet( ads1115EventHandle) == 0  )
            {
                    // log_e("ads1115 set rcv data *** .....");
                my_ads1115.time_ticks =  osKernelGetTickCount( );
                osEventFlagsSet( ads1115EventHandle, ADS1115_Event_RCV_DATA );
                if ( HAL_I2C_Master_Receive_IT( pADS1115_I2C, ADS1115_READ_ADDRESS, my_ads1115.result , 2 ) != HAL_OK  )
                {
                    // log_e("ads1115 set register failure while reading!!!");
                    my_ads1115.state  =   ADS1115_WORK_STATE_ERROR ;
                }
            }
            if ( (osKernelGetTickCount() - my_ads1115.time_ticks) > 5 *1000 )
            {
                my_ads1115.state  =  ADS1115_WORK_STATE_TIMEOUT ;
            }
            break;   
        case ADS1115_WORK_STATE_RCV_DATA_SUCCESS:
            // log_w("ads1115 rcv data .....succ   result : %d ", my_ads1115.result );
            osEventFlagsClear( ads1115EventHandle, ADS1115_Event_RCV_DATA );
            osEventFlagsSet( ads1115EventHandle, ADS1115_Event_READY  );
            my_ads1115.state  =   ADS1115_WORK_STATE_DATA_OK ;

            // log_i(  "ad val :  %d ", 256*my_ads1115.result[0] +my_ads1115.result[1] );
            break;  
        case ADS1115_WORK_STATE_DATA_OK:
            osDelay(20);
            break;  
        case ADS1115_WORK_STATE_ERROR:
            log_e("ads1115 error!!!");
            break;    
        case ADS1115_WORK_STATE_TIMEOUT:
            log_e("ads1115 timeout!!!");
            break;
        case ADS1115_WORK_STATE_STOP:
            break;      
        default:
            break;
        }
        osDelay( 20 );

    }   
}

void ads1115_port(void)
{
    ads1115TaskHandle = osThreadNew(ads1115_task, NULL, &ads1115Task_attributes);
    ads1115EventHandle = osEventFlagsNew ( &ads1115Event_attributes );
}

/**
 * @brief
 * @param [in] ads1115_I2cHandle
 * @param [in] pointADD   -- 读的寄存器地址
 * @param [in] configH
 * @param [in] configL
 *
 * @details
 */
int ads1115_init()
{
    uint8_t reg_data[3]; 
    my_ads1115.hi2c= pADS1115_I2C;
    my_ads1115.config_H = my_ads1115.config_os|my_ads1115.config_mux
                |my_ads1115.config_PGA|my_ads1115.config_MODE;
    my_ads1115.config_L = my_ads1115.config_DR|my_ads1115.config_COMP_MODE|my_ads1115.config_COMP_POL
            |my_ads1115.config_COMP_LAT|my_ads1115.config_COMP_QUE ;
    my_ads1115.reg_data[0] = 0x01;                 //  point addr  8bit  配置寄存器  0x01
    my_ads1115.reg_data[1] = my_ads1115.config_H;  //  config_reg 高位
    my_ads1115.reg_data[2] = my_ads1115.config_L;  //  config_reg 低位

    ads1115_set_state( ADS1115_WORK_STATE_INIT );
    // osEventFlagsSet ( ads1115EventHandle, ADS1115_Event_INIT );
    // if (HAL_I2C_Master_Transmit_IT(pADS1115_I2C, ADS1115_WRITE_ADDRESS, my_ads1115.reg_data, 3 ) != HAL_OK)
    // {
    //     return -1;
    // }
    return 0;
}

int ads1115_test()
{

    return 0;
}

void ads1115_start( )  // set register开始测量
{
    osEventFlagsSet( ads1115EventHandle, ADS1115_Event_READY );
    ads1115_set_state( ADS1115_WORK_STATE_SET_REGISTER );
}
void ads1115_stop( )  // 结束测量  等待
{
    ads1115_set_state( ADS1115_WORK_STATE_WAITING );
}

int ads1115_setup(ADS1115_REG_CONFIG_MUX_Diff_TypeDef mux)
{
    my_ads1115.config_mux &= mux;
    my_ads1115.config_H  =my_ads1115.config_os|my_ads1115.config_mux
                |my_ads1115.config_PGA|my_ads1115.config_MODE;
    my_ads1115.reg_data[1] = my_ads1115.config_H;
    return 0;
}

void ads1115_set_event_flags(ADS1115_Event_TypeDef evt)
{
    osEventFlagsSet ( ads1115EventHandle, evt );
}

void ads1115_set_state(ADS1115_WORK_STATE_TypeDef state)
{
    my_ads1115.state = state;
}

int16_t ads1115_read_data( )
{
    int16_t data;
    uint8_t rx_data[2] = {0};

    // TODO 阻塞式， 改为 DMA 中断模式
    // 读寄存器 0x00 十六位
    while (HAL_I2C_Master_Transmit(pADS1115_I2C, ADS1115_WRITE_ADDRESS, 0x00, 1, 2000) != HAL_OK)
    // while ( HAL_I2C_Master_Transmit_IT(pADS1115_I2C, ADS1115_WRITE_ADDRESS, 0x00, 1 ) != HAL_OK )
    {
        if (HAL_I2C_GetError(pADS1115_I2C) != HAL_I2C_ERROR_AF)
        {
            printf("ads1115 convert Register error!!!\r\n");
        }
    }
    // 读两位
    // while (HAL_I2C_Master_Receive(pADS1115_I2C, ADS1115_READ_ADDRESS, rx_data, 2, 2000) != HAL_OK)
    while ( HAL_I2C_Master_Receive_IT(pADS1115_I2C, ADS1115_READ_ADDRESS, rx_data, 2 ) != HAL_OK )
    {
        if ( HAL_I2C_GetError(pADS1115_I2C) != HAL_I2C_ERROR_AF )
        {
            printf("ads1115 read data error!!!\r\n");
        }
    }
    data = rx_data[0] * 256 + rx_data[1];
    return data;
}

double ads1115_get_voltage_val( )
{
    double val;
    int16_t ad_val;
    //  TODO  去掉延时，使用寄存器的指示,  setup  和读取数据分开执行
    // ads1115_setup( pADS1115_I2C, pointADD, configH, configL );
    // ads1115_setup( ADS1115_REG_CONFIG_MUX_SINGLE_0 );
    
    HAL_Delay(10);
    // ad_val = ads1115_read_data( pADS1115_I2C );
    ad_val = my_ads1115.result[0] * 256 + my_ads1115.result[1];
    if ( (ad_val == 0x7FFF) | (ad_val == 0X8000)) // 是否超量程了
    {
        ad_val = 0;
        // printf("over PGA\r\n");
    }
    switch ((0x0E & my_ads1115.config_H) >> 1) // 量程对应的分辨率
    {
    case (0x00):
        val = (double)ad_val * 187.5 / 1000.0; //
        break;
    case (0x01):
        val = (double)ad_val * 125 / 1000.0;
        break;
    case (0x02):
        val = (double)ad_val * 62.5 / 1000.0;
        break;
    case (0x03):
        val = (double)ad_val * 31.25 / 1000.0;
        break;
    case (0x04):
        val = (double)ad_val * 15.625 / 1000.0;
        break;
    case (0x05):
        val = (double)ad_val * 7.8125 / 1000.0;
        break;
    }
    return (my_ads1115.unit == ADS1115_OUTPUT_UNIT_mv)?val:(val/1000.0);
}

uint16_t ADS1115_Get_Coeff_BY_128(  )
{
    uint16_t val;
 
    switch ((0x0E & my_ads1115.config_H) >> 1) // 量程对应的分辨率
    {
    case (0x00):
        val = (int)(  187.5 * 128.0); //
        break;
    case (0x01):
        val = (int)(  125.5 * 128.0);   
        break;
    case (0x02):
        val = (int)(   62.5 * 128.0); 
        break;
    case (0x03):
        val = (int)(  31.25 * 128.0);  
        break;
    case (0x04):
        val = (int)(  15.625 * 128.0);  
        break;
    case (0x05):
        val = (int)(  7.8125 * 128.0);  
        break;
    }

    return val;
}

double ADS1115_Get_Voltage_From_U16( uint16_t voltage)
{
    double val;
    if ( ( voltage == 0x7FFF) | (voltage == 0X8000)) // 是否超量程了
    {
        voltage = 0;
        // printf("over PGA\r\n");
    }
    switch ((0x0E & my_ads1115.config_H) >> 1) // 量程对应的分辨率
    {
    case (0x00):
        val = (double)voltage * 187.5 / 1000.0; //
        break;
    case (0x01):
        val = (double)voltage * 125 / 1000.0;
        break;
    case (0x02):
        val = (double)voltage * 62.5 / 1000.0;
        break;
    case (0x03):
        val = (double)voltage * 31.25 / 1000.0;
        break;
    case (0x04):
        val = (double)voltage * 15.625 / 1000.0;
        break;
    case (0x05):
        val = (double)voltage * 7.8125 / 1000.0;
        break;
    }

    return val;
}

//主机模式发送回调函数
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *I2cHandle)
{
    if (I2cHandle == pADS1115_I2C)
    {
        log_i("ads1115 send cplt...");
        if (  my_ads1115.state  == ADS1115_WORK_STATE_INIT )    
        {
            my_ads1115.state  = ADS1115_WORK_STATE_INIT_SUCCESS;
            // osEventFlagsSet( ads1115EventHandle, ADS1115_Event_INIT_SUCCESS );
            // osEventFlagsClear( ads1115EventHandle, ADS1115_Event_INIT );
        }
        if ( my_ads1115.state  == ADS1115_WORK_STATE_SET_REGISTER )    
        {
             my_ads1115.state  = ADS1115_WORK_STATE_SET_REGISTER_SUCCESS;
            // osEventFlagsSet( ads1115EventHandle, ADS1115_Event_SET_REGISTER_SUCCESS );
        }
        if ( my_ads1115.state  == ADS1115_WORK_STATE_SET_POINT_ADDR )    
        {
             my_ads1115.state  = ADS1115_WORK_STATE_SET_POINT_ADDR_SUCCESS;
            // osEventFlagsSet( ads1115EventHandle, ADS1115_Event_TRANS_SUCCESS );
        }
    }
}
//主机模式接收回调函数
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *I2cHandle)
{
    if (I2cHandle == pADS1115_I2C)
    {
        log_i("ads1115 rcv cplt...");
        if ( my_ads1115.state  == ADS1115_WORK_STATE_RCV_DATA )   
        {
             my_ads1115.state  = ADS1115_WORK_STATE_RCV_DATA_SUCCESS;
            // osEventFlagsSet( ads1115EventHandle, ADS1115_Event_RCV_DATA_SUCCESS );
        }
    }
}


// int ads1115_test()
// {

//     log_i(  "ads1115_test  ->    "  );
//     uint32_t flag;

//     flag = osEventFlagsWait ( ads1115EventHandle,
//        ADS1115_Event_READY|ADS1115_Event_INIT|ADS1115_Event_SET_REGISTER|ADS1115_Event_SET_POINT_ADDR|ADS1115_Event_RCV_DATA,    
//                                         0,  
//                                         10);  
//     log_i(  "flag  ->  %d ", flag );

 
//     log_i(  "   ->  %d ", osEventFlagsGet( ads1115EventHandle) );
//     osEventFlagsSet( ads1115EventHandle, ADS1115_Event_READY ) ;
//     log_i(  "  ready ->  %d ", osEventFlagsGet( ads1115EventHandle) );
//      osEventFlagsSet( ads1115EventHandle, ADS1115_Event_INIT ) ;
//     log_i(  "  init ->  %d ", osEventFlagsGet( ads1115EventHandle) );

//      osEventFlagsSet( ads1115EventHandle, ADS1115_Event_RCV_DATA ) ;
//     log_i(  " set register ->  %d ", osEventFlagsGet( ads1115EventHandle) );

//      osEventFlagsSet( ads1115EventHandle, ADS1115_Event_SET_REGISTER ) ;
//      osEventFlagsSet( ads1115EventHandle, ADS1115_Event_SET_POINT_ADDR ) ;
//     log_i(  " set register ->  %d ", osEventFlagsGet( ads1115EventHandle) );


//      osEventFlagsClear( ads1115EventHandle, ADS1115_Event_SET_POINT_ADDR ) ;
//     log_i(  " clear  ->  %d ", osEventFlagsGet( ads1115EventHandle) );
//         flag = osEventFlagsWait ( ads1115EventHandle,
//        ADS1115_Event_READY|ADS1115_Event_INIT|ADS1115_Event_SET_REGISTER|ADS1115_Event_SET_POINT_ADDR|ADS1115_Event_RCV_DATA,    
//                                         0,  
//                                         10);  
//     log_i(  "flag 2  ->  %d ", flag );

//     if (flag&ADS1115_Event_SET_POINT_ADDR == 0)
//     {
//         log_i("get ...... ");
//     }else{
//         log_i(" not get ... ");

//     }

//     return 0;
// }
