// i2c_ads1115.c
#include "i2c_ads1115.h"
#include "stdlib.h"
#include "stdio.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,
        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,  // 默认输出毫伏
};

void ads1115_task(void)
{
    uint32_t event_flags;
    for (;;)
    {
        // 启用中断发送,判断状态, 
        // 地址中断， 确认是哪I2C 设备通讯
        /* code */
        /*  TODO 统一的超时机制 */

        /*  事件来管理 */
        event_flags = osEventFlagsWait ( 
                ads1115EventHandle
                , ADS1115_Event_READY|ADS1115_Event_INIT|ADS1115_Event_TRANS_ONLY|ADS1115_Event_DATA_RCV
                , 0
                , portMAX_DELAY );
        if ( event_flags & (ADS1115_Event_READY|ADS1115_Event_INIT) 
                    == (ADS1115_Event_READY|ADS1115_Event_INIT)  )
        {
            // if (HAL_I2C_GetError(&hi2c1)!= HAL_I2C_ERROR_AF)
            // {
            //     Error_Handler();
            // }
            // if (HAL_I2C_GetState(&hi2c1)!= HAL_I2C_STATE_READY)
            // {
            //     Error_Handler();
            // }

            osEventFlagsClear(ads1115EventHandle, ADS1115_Event_INIT);
            osEventFlagsSet(ads1115EventHandle, ADS1115_Event_INIT_SUCCESS);
        }

        if ( event_flags & ( ADS1115_Event_READY|ADS1115_Event_TRANS_ONLY ) 
                    == (ADS1115_Event_READY|ADS1115_Event_TRANS_ONLY) )
        {
            osEventFlagsClear(ads1115EventHandle, ADS1115_Event_TRANS_ONLY);
            
        }

        if ( event_flags & ( ADS1115_Event_READY|ADS1115_Event_TRANS_FOR_DATA ) 
                    == (ADS1115_Event_READY|ADS1115_Event_TRANS_FOR_DATA) )
        {
            osEventFlagsClear(ads1115EventHandle, ADS1115_Event_TRANS_FOR_DATA);
            osEventFlagsSet(ads1115EventHandle, ADS1115_Event_DATA_RCV);
            
        }
        if ( event_flags & ( ADS1115_Event_READY|ADS1115_Event_DATA_RCV ) 
                    == ( ADS1115_Event_READY|ADS1115_Event_DATA_RCV ) )
        {
            osEventFlagsClear( ads1115EventHandle, ADS1115_Event_DATA_RCV );           
        }
        // __HAL_I2C_GET_FLAG(&hi2c1, I2C_FLAG_TXE) ;
        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 ;
    reg_data[0] = 0x01;                 //  point addr  8bit  配置寄存器
    reg_data[1] = my_ads1115.config_H;  //  config_reg 高位
    reg_data[2] = my_ads1115.config_L;  //  config_reg 低位

    // TODO 阻塞式， 改为 DMA 中断模式， 配合定时器 ， 或启用中断等待
    // while (HAL_I2C_Master_Transmit(pADS1115_I2C, ADS1115_WRITE_ADDRESS, reg_data, 3, 2000) != HAL_OK)
    // {
    //     if (HAL_I2C_GetError(pADS1115_I2C) != HAL_I2C_ERROR_AF)
    //     {
    //         printf("ads1115 Config Register error!!!\r\n");
    //     }
    // }

    osEventFlagsSet ( ads1115TaskHandle, ADS1115_Event_INIT );
    if (HAL_I2C_Master_Transmit_IT(pADS1115_I2C, ADS1115_WRITE_ADDRESS, reg_data, 3 ) != HAL_OK)
    {
        return -1;
    }
    return 0;

}

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_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");
    }
    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);

}