// i2c_ads1115.c
#include "bsp_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"
};


I2C_HELPER_TypeDef *ads1115_i2c_helper;

// uint16_t  resultbuf[1] = {0};
// double  result_double = 0;

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,
        0,
        0,
        { 0, 0, 0 },
        ADS1115_OUTPUT_UNIT_mv,  // 默认输出毫伏
        0,
        0.0,  //  coeff  放大1000
        0.0,   // voltage——mv
        ADS1115_WORK_STATE_WAITING,
        0,
};

void ads1115_task(void)
{
    uint8_t rx_data[2] = {0};
    my_ads1115.event_flag = 0;
    uint64_t  ticks;
    int err_con = 0;
    int st;

    for ( ; ; )
    {   
        switch (my_ads1115.state)
        {
        case ADS1115_WORK_STATE_WAITING:
            // log_e( " ADS1115 waiting  ********** "  );
            osDelay(20);
            break;
        case ADS1115_WORK_STATE_START:
            break;     

        case ADS1115_WORK_STATE_TEST:
            log_e( " ADS1115 test  ********** %d"  ,pADS1115_I2C->State  );
            ads1115_get_reg_data( );

            I2C_HELPER_Set_mem_addr( ads1115_i2c_helper, 0x01 );
            st = I2C_HELPER_Trans( ads1115_i2c_helper, my_ads1115.reg_data, 2 );
            if ( st != HAL_OK)
            {
                log_w( " ADS1115 init  **********  trans error "  );
                my_ads1115.state = ADS1115_WORK_STATE_ERROR;;
                break;
            } 
            ticks =  osKernelGetTickCount();
            err_con = 0;
            my_ads1115.state = ADS1115_WORK_STATE_TESTING;
            continue; 
        case ADS1115_WORK_STATE_TESTING:
            if ( osKernelGetTickCount() - ticks > 1000 )
            {
                err_con++;
                if( err_con >3)
                {
                    log_w( " ADS1115 testing  ******** error "  );
                    my_ads1115.state = ADS1115_WORK_STATE_ERROR;
                }
                my_ads1115.state = ADS1115_WORK_STATE_TEST;                
            }
            osDelay(1);
            continue;
        case ADS1115_WORK_STATE_TEST_OK:
            log_w( " ADS1115 TEST_OK  ********** %d"  ,pADS1115_I2C->State  );
            my_ads1115.state = ADS1115_WORK_STATE_GET_DATA_READY;
            // TODO Stop  DMA   
            continue;

        case ADS1115_WORK_STATE_GET_DATA_READY:
            osDelay(1);
            continue; 

        case ADS1115_WORK_STATE_GET_DATA_START:
            log_w( " ADS1115 GET_DATA_START  ********** %d " , pADS1115_I2C->State  ); 
            my_ads1115.result_int16 = 0 ;
            my_ads1115.voltage_mv   = 0.0 ;
            ads1115_get_reg_data( );
            ads1115_get_coeff( );
            my_ads1115.state = ADS1115_WORK_STATE_GET_DATA_SET_REG01;
            continue;
       case ADS1115_WORK_STATE_GET_DATA_SET_REG01:
            I2C_HELPER_Set_mem_addr( ads1115_i2c_helper, 0x01 );
            st = I2C_HELPER_Trans( ads1115_i2c_helper, my_ads1115.reg_data, 2 );
            if ( st != HAL_OK)
            {
                log_w( " ADS1115 init  **********  trans error "  );
                my_ads1115.state = ADS1115_WORK_STATE_ERROR;;
                break;
            } 
            ticks =  osKernelGetTickCount();
            err_con = 0;
            my_ads1115.state = ADS1115_WORK_STATE_GET_DATA_SET_REG01_Wait;
            continue;
        case ADS1115_WORK_STATE_GET_DATA_SET_REG01_Wait:
            if ( osKernelGetTickCount() - ticks > 1000 )
            {
                err_con++;
                if( err_con >3)
                {
                    log_w( " ADS1115 set reg   ******** error "  );
                    my_ads1115.state = ADS1115_WORK_STATE_ERROR;
                }
                my_ads1115.state = ADS1115_WORK_STATE_GET_DATA_START;                
            }
            osDelay(1);
            continue; 
        case ADS1115_WORK_STATE_GET_DATA_RCV:
            log_i( " ADS1115 Ready  ********** _DATA_RCV   "   );
            memset( rx_data,0,2);
            I2C_HELPER_Set_mem_addr(ads1115_i2c_helper, 0x00);
            st = I2C_HELPER_Start_Rcv(ads1115_i2c_helper, rx_data, 2);    
            if ( st != HAL_OK)
            {
                log_w( " ADS1115 init  **********  trans error "  );
                my_ads1115.state = ADS1115_WORK_STATE_ERROR;;
                break;
            }   
            ticks =  osKernelGetTickCount();
            err_con = 0;
            my_ads1115.state = ADS1115_WORK_STATE_GET_DATA_RCV_Wait;
            continue;
        case ADS1115_WORK_STATE_GET_DATA_RCV_Wait:
            if ( osKernelGetTickCount() - ticks > 1000 )
            {
                err_con++;
                if( err_con >3)
                {
                    log_w( " ADS1115 data rcv  ******** error "  );
                    my_ads1115.state = ADS1115_WORK_STATE_ERROR;
                }
                my_ads1115.state = ADS1115_WORK_STATE_GET_DATA_START;                
            }
            osDelay(1);
            continue; 
        case ADS1115_WORK_STATE_GET_DATA_OK:
            log_i( " ADS1115   **********   DATA_OK   %d" ,my_ads1115.result_int16 );
            double val;
            my_ads1115.result_int16 = rx_data[0] * 256 + rx_data[1];
            if ( (my_ads1115.result_int16  == 0x7FFF) | (my_ads1115.result_int16  == 0X8000)) // 是否超量程了
            {
                my_ads1115.result_int16 = 0;
            }
            my_ads1115.voltage_mv =  ((double)my_ads1115.result_int16 *(double) my_ads1115.coeff)/1000.0;;
            log_i(  " voltage mv :    %06f",my_ads1115.voltage_mv);
            my_ads1115.state  = ADS1115_WORK_STATE_STOP ;
            break;    
        case ADS1115_WORK_STATE_ERROR:
            log_w( " ADS1115 error ..... "  );
            // my_ads1115.state  = ADS1115_WORK_STATE_WAITING ;
            osDelay(10);
            continue;    
        case ADS1115_WORK_STATE_STOP:
            log_w( " ADS1115 stop..... "  );
            // my_ads1115.state  = ADS1115_WORK_STATE_WAITING ;
            osDelay(10);
            continue;  
        default:
            break;
        }
 
        osDelay(200);
    } 
}

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(void)
{
    ads1115_i2c_helper = I2C_HELPER_Init( );
    I2C_HELPER_Set_Hi2c( ads1115_i2c_helper,  pADS1115_I2C );
    I2C_HELPER_Set_dev_addr( ads1115_i2c_helper, ADS1115_WRITE_ADDRESS);
    I2C_HELPER_Set_mem_addr_size( ads1115_i2c_helper,  I2C_MEMADD_SIZE_8BIT );  //I2C_MEMADD_SIZE_16BIT
    // I2C_HELPER_Set_mem_addr(ads1115_i2c_helper, uint16_t mem_addr);

    I2C_HELPER_Setup_Trans_mode( ads1115_i2c_helper, I2C_Trans_IT );

    //  设置回调
    I2C_HELPER_Set_Callback( ads1115_i2c_helper,  (void *)&my_ads1115, (i2c_callback_fun) ads1115_callback);

    // ads1115_get_reg_data( );
    // // polling mode test, cfg register : 0x01
    // int st = 0;
    // st = HAL_I2C_Mem_Write( ads1115_i2c_helper->hi2c, ADS1115_WRITE_ADDRESS, 0x01, 
    //         ads1115_i2c_helper->mem_addr_size, my_ads1115.reg_data, 2, 0xFFFF );

    // if (st != HAL_OK)
    // {
    //     return -1;
    // }
    return 0;
}

int ads1115_test(void)
{
    my_ads1115.state = ADS1115_WORK_STATE_TEST;
}

void ads1115_start(void)
{
    my_ads1115.state =ADS1115_WORK_STATE_GET_DATA_START;
    // osEventFlagsSet( ads1115TaskHandle, ADS1115_Event_Get_Data );
}

void ads1115_stop(void)
{
}

int ads1115_setup(ADS1115_REG_CONFIG_MUX_Diff_TypeDef mux)
{
    my_ads1115.config_H &= ~0x70;
    my_ads1115.config_H &= mux;
    return 0;
}


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)
    {
        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)
    {
        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_coeff( )
{
    my_ads1115.coeff = 1.0;
    switch ((0x0E & my_ads1115.config_H) >> 1) // 量程对应的分辨率
    {
    case (0x00):
        my_ads1115.coeff =my_ads1115.coeff * 187.5 ; //
        break;
    case (0x01):
        my_ads1115.coeff = my_ads1115.coeff * 125 ;
        break;
    case (0x02):
        my_ads1115.coeff = my_ads1115.coeff * 62.5;
        break;
    case (0x03):
        my_ads1115.coeff = my_ads1115.coeff * 31.25 ;
        break;
    case (0x04):
        my_ads1115.coeff = my_ads1115.coeff * 15.625;
        break;
    case (0x05):
        my_ads1115.coeff = my_ads1115.coeff * 7.8125;
        break;
    }
}

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 );
    if ( (ad_val == 0x7FFF) | (ad_val == 0X8000)) // 是否超量程了
    {
        ad_val = 0;
        // printf("over PGA\r\n");
    }
    ads1115_get_coeff( );
    val = ad_val * my_ads1115.coeff/1000.0;

    if (my_ads1115.unit == ADS1115_OUTPUT_UNIT_v)
    {
        val = val/1000.0;
    }
    return val;
}

 
void ads1115_get_data_start(void)
{
    // log_w( " ADS1115    ********** start.. "  );
    // osEventFlagsSet( ads1115TaskHandle, ADS1115_Event_Get_Data );   
    my_ads1115.state =ADS1115_WORK_STATE_GET_DATA_START;
} 


void ads1115_callback(ADS1115_TypeDef *pAds1115, uint8_t *buf, uint16_t size)
{
    switch (my_ads1115.state)
    {
        case ADS1115_WORK_STATE_TESTING :
            my_ads1115.state++;
            break;
        case ADS1115_WORK_STATE_GET_DATA_SET_REG01_Wait :
            my_ads1115.state++;
            break;
        case ADS1115_WORK_STATE_GET_DATA_RCV_Wait :
            // TODO Check data?
            my_ads1115.state++;
            break;        
        default:
            break;
    }
 
} 
 

// 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); /* 指定超时事件,无限等待 */
    // TODO 阻塞式 仅init 使用
    // my_ads1115.state = ADS1115_WORK_STATE_INIT;
    // osEventFlagsSet ( ads1115TaskHandle, ADS1115_Event_INIT );

    // I2C_HELPER_Set_mem_addr(ads1115_i2c_helper, 0x01);
    // st = I2C_HELPER_Trans(ads1115_i2c_helper, reg_data,2);

    // I2C_HELPER_Set_mem_addr(ads1115_i2c_helper, 0x00);
    // st = I2C_HELPER_Start_Rcv(ads1115_i2c_helper, rx_data, 2);





    // st = HAL_I2C_Mem_Write(ads1115_i2c_helper->hi2c, ads1115_i2c_helper->dev_addr, my_ads1115.reg_data[0],ads1115_i2c_helper->mem_addr_type ,  reg_data,2,0xFFFF);
    // if (HAL_I2C_Master_Transmit(pADS1115_I2C, ADS1115_WRITE_ADDRESS, my_ads1115.reg_data, 3,1000 ) != HAL_OK)
    // {
    //     return -1;
    // }
    // while (HAL_I2C_Master_Transmit(pADS1115_I2C, ADS1115_WRITE_ADDRESS, 0x00, 1, 2000) != 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)
    // {
    //     if ( HAL_I2C_GetError(pADS1115_I2C) != HAL_I2C_ERROR_AF )
    //     {
    //         printf("ads1115 read data error!!!\r\n");
    //     }
    // }




            // case ADS1115_WORK_STATE_GET_DATA_Convert_Register:
            // log_i( " ADS1115 Ready  **********  Convert_Register "  );

            // while (HAL_I2C_Master_Transmit(pADS1115_I2C, ADS1115_WRITE_ADDRESS, 0x00, 1, 2000) != HAL_OK)
            // {
            //     if (HAL_I2C_GetError(pADS1115_I2C) != HAL_I2C_ERROR_AF)
            //     {
            //         printf("ads1115 convert Register error!!!\r\n");
            //     }
            // }
            // my_ads1115.state = ADS1115_WORK_STATE_GET_DATA_RCV;
 

            // // // osEventFlagsClear( ads1115TaskHandle, ADS1115_Event_Get_Data );  
            // // st = HAL_I2C_Master_Transmit (pADS1115_I2C, ADS1115_WRITE_ADDRESS, 0x00, 1 ,1000);
            // // if ( st != HAL_OK)
            // // {
            // //     log_e( " ADS1115 init  ********** Convert_Register error "  );
            // //     my_ads1115.state = ADS1115_WORK_STATE_ERROR;
            // //     break;
            // // } 
            // // if ( HAL_I2C_GetError(pADS1115_I2C) != HAL_I2C_ERROR_AF )
            // // {
            // //     log_e("ads1115 read data error!!!\r\n");
            // //     break;
            // // } 
            // // my_ads1115.state =ADS1115_WORK_STATE_GET_DATA_RCV;
            // // if  (HAL_I2C_Master_Transmit_IT(pADS1115_I2C, ADS1115_WRITE_ADDRESS, 0x00, 1 ) != HAL_OK) {
            // //      my_ads1115.state =ADS1115_WORK_STATE_ERROR;
            // // }
            // // if ( HAL_I2C_GetError(pADS1115_I2C) != HAL_I2C_ERROR_AF )
            // // {
            // //     printf("ads1115 convert Register error!!!\r\n");
            // // } 

            // // event_flags = osEventFlagsWait ( ads1115EventHandle, 
            // //         ADS1115_Event_Get_Data_Convert_Register, 0 , portMAX_DELAY );
            // //  if (event_flags && ADS1115_Event_Get_Data_Convert_Register)
            // // {
            // //     my_ads1115.state = ADS1115_WORK_STATE_GET_DATA_RCV;
            // // }
 
            // continue;