#include "bsl_hs3003.h"
#include "hal_data.h"
#include "bsp_hw_i2c.h"
#include "FreeRTOS.h"
#include "task.h"


/*******************************************************************************
 * Macro Definitions
 ******************************************************************************/
#define HS300x_I2C_SLAVE_ADDR_7BIT           (0x44U)

#define HS300X_DATA_VALID                    (0x00U)
#define HS300X_DATA_STALE                    (0x01U)
#define HS300X_STATUS_MASK                   (0xC0000000U)
#define HS300X_STATUS_POS                    (30U)

#define HS300X_DATA_MASK                     (0x3FFFFFFCU)
#define HS300X_HUMI_DATA_MASK                (0x3FFF0000U)
#define HS300X_HUMI_DATA_POS                 (16U)
#define HS300X_TEMP_DATA_MASK                (0x0000FFFCU)
#define HS300X_TEMP_DATA_POS                 (2U)

/* calculation formula, 2^14 - 1 */
#define HS300X_DATA_FACTOR                   (16383U)

/*******************************************************************************
 * Static Variables Definitions
 ******************************************************************************/

/*******************************************************************************
 * Static Function Declarations
 ******************************************************************************/
static void Hs300x_ReadFromI2C(uint8_t *data_buffer, uint8_t data_len);
static void Hs300x_WriteToI2C(uint8_t *data_buffer, uint8_t data_len);
static bool Hs300x_DataConvert(uint32_t read_data, s_Hs300xDataType *cal_result);

/*******************************************************************************
 * Function Definitions
 ******************************************************************************/
/*********************Hs300x读数据函数************************************/
static void Hs300x_ReadFromI2C(uint8_t *data_buffer, uint8_t data_len)
{
    fsp_err_t err;
    uint32_t timeout_ms = 100;

    R_SCI_I2C_SlaveAddressSet(&g_i2c6_ctrl,
                            HS300x_I2C_SLAVE_ADDR_7BIT,
                            I2C_MASTER_ADDR_MODE_7BIT);

    err = R_SCI_I2C_Read(&g_i2c6_ctrl, data_buffer, data_len, true);
    assert(FSP_SUCCESS == err);

    /* Since there is nothing else to do, block until Callback triggers*/
    while ((I2C_MASTER_EVENT_TX_COMPLETE != sci_i2c6_event) && timeout_ms>0)
    {
        R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS);
        timeout_ms--;
    }

    if (I2C_MASTER_EVENT_ABORTED == sci_i2c6_event)
    {
        __BKPT(0);
    }
    /* Read data back from the I2C slave */
    sci_i2c6_event = I2C_MASTER_EVENT_ABORTED;

}

/*********************Hs300x写数据函数************************************/
static void Hs300x_WriteToI2C(uint8_t *data_buffer, uint8_t data_len)
{
    fsp_err_t err;
    uint32_t timeout_ms = 100;

    R_SCI_I2C_SlaveAddressSet(&g_i2c6_ctrl,
                                    HS300x_I2C_SLAVE_ADDR_7BIT,
                                    I2C_MASTER_ADDR_MODE_7BIT);

    err = R_SCI_I2C_Write(&g_i2c6_ctrl, data_buffer, data_len, true);
    assert(FSP_SUCCESS == err);

    /* Since there is nothing else to do, block until Callback triggers*/
    while ((I2C_MASTER_EVENT_TX_COMPLETE != sci_i2c6_event) && timeout_ms>0)
    {
        R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS);
        timeout_ms--;
    }

    if (I2C_MASTER_EVENT_ABORTED == sci_i2c6_event)
    {
        __BKPT(0);
    }
    /* Read data back from the I2C slave */
    sci_i2c6_event = I2C_MASTER_EVENT_ABORTED;

}

static bool Hs300x_DataConvert(uint32_t read_data, s_Hs300xDataType *cal_result)
{
    uint32_t humi_data;
    uint32_t temp_data;

    if (((read_data & HS300X_STATUS_MASK) >> HS300X_STATUS_POS) == HS300X_DATA_VALID)
    {
        // Data is valid
        humi_data = (read_data & HS300X_HUMI_DATA_MASK) >> HS300X_HUMI_DATA_POS;
        temp_data = (read_data & HS300X_TEMP_DATA_MASK) >> HS300X_TEMP_DATA_POS;

        // Calculate the humidity: humi_data/(2^14-1) * 100
        cal_result->humi = (double)humi_data/(double)(HS300X_DATA_FACTOR) * 100.0;
        // Calculate the temperature: temp_data/(2^14-1) * 165 - 40
        cal_result->temp = (double)temp_data/(double)(HS300X_DATA_FACTOR) * 165.0 - 40;

        return true;
    }
    else
    {
        return false;
    }
}

void Hs300x_Init(void)
{
    // Do not settings, keep default settings in sensor device
}

s_Hs300xDataType Hs300x_ReadData(void)
{
    uint8_t data[4];
    uint32_t data_u32;
    s_Hs300xDataType humi_temp;

    // Write address start measurement
    Hs300x_WriteToI2C(NULL, 0);
    // Delay 50ms for waiting for convert finished
    vTaskDelay(50);
    // Read measurement from sensor HS300X
    Hs300x_ReadFromI2C(data, 4);
    // Convert the data to 32bit
    data_u32 = (uint32_t)((data[0] << 24U) |
                          (data[1] << 16U) |
                          (data[2] << 8U) |
                          (data[3]));
    // Read the temperature and hunidity
    (void)Hs300x_DataConvert(data_u32, &humi_temp);

    return humi_temp;
}
