/*
 * Copyright (c) 2020 Great Master Wu. All rights reserved.
 * Author    Date          ChangeLog
 * Master    2021-03-25    Initialize version
 */
#include "aw2013.h"
#include "sensor_error.h"
 
/**
 * This register can also be used for ID register when reading. 
 * The value is 33h when reading this register.
*/
bool aw2013_check_id(aw2013_dev_t *dev)
{
    DEV_ASSERT(dev);
    uint8_t buf[] = {AW_REG_RESET, 0};
    sensor_serial_if_t *driver = dev->driver;

    aw2013_reset(dev);
    sensor_delay_us(2);
    driver->read_reg(driver,buf, 1);

    if(buf[1] == AW2013_CHIPID)
    {
        return true;
    }

    return false;
}


/**
 * Set this register to 55h, all of the circuits in AW2013 will be 
 * reset and the configurable registers will be reset to default value
*/
int aw2013_reset(aw2013_dev_t *dev)
{
    DEV_ASSERT(dev);
    uint8_t buf[] = {AW_REG_RESET, AW_RESET_CMD};
    sensor_serial_if_t *driver = dev->driver;

    return driver->write_reg(driver,buf, 1);
}


/*
 * the interrupt flag is read from ISR
 * @param state - is the combine of LIEn_STATE_t | LED_FUNCTION_STATE_t
*/
int aw2013_set_global_control(aw2013_dev_t *dev, uint8_t state)
{
    DEV_ASSERT(dev);
    uint8_t buf[] = {AW_REG_GLOBAL_CONTROL, state};
    sensor_serial_if_t *driver = dev->driver;

    return driver->write_reg(driver,buf, 1);
}


int aw2013_enter_sleep(aw2013_dev_t *dev)
{
    DEV_ASSERT(dev);
    uint8_t buf[] = {AW_REG_GLOBAL_CONTROL, LED_FUNCTION_DISABLE};
    sensor_serial_if_t *driver = dev->driver;

    return driver->write_reg(driver,buf, 1);
}


/*
 * @param state - result & with LIEn_STATE_t and LED_FUNCTION_STATE_t
*/
int aw2013_get_global_control(aw2013_dev_t *dev, uint8_t *state)
{
    DEV_ASSERT(dev);
    int ret;
    uint8_t buf[] = {AW_REG_GLOBAL_CONTROL, 0};
    sensor_serial_if_t *driver = dev->driver;

    ret = driver->read_reg(driver,buf, 1);
    
    return ret;
}


/*
 * after read use LISn_INDICATOR_MASK & status == LISn_INDICATOR_MASK
*/
int aw2013_get_interrupt_status(aw2013_dev_t *dev, uint8_t *status)
{
    DEV_ASSERT(dev);
    int ret;
    uint8_t buf[] = {AW_REG_INT_STATUS, 0};
    sensor_serial_if_t *driver = dev->driver;

    ret = driver->read_reg(driver,buf, 1);
    *status = buf[1];
    
    return ret;
}

/*
 * @param led[0-2] ~ LED[0-2]
 * @param mode - combine of MAX_CURRENT_SETTING_t | OPERATING_MODE_t |
 * FADE_IN_STATE_t| FADE_OUT_STATE_t
*/
int aw2013_set_control_mode(aw2013_dev_t *dev, LED_INDEX_t index, uint8_t mode)
{
    DEV_ASSERT(dev);
    
    uint8_t buf[] = {0, mode};
    sensor_serial_if_t *driver = dev->driver;
    if(index == 0)
        buf[0] = AW_REG_LED0_MODE_CONTROL;
    else if(index == 1)
        buf[0] = AW_REG_LED1_MODE_CONTROL;
    else if(index == 2)
        buf[0] = AW_REG_LED2_MODE_CONTROL;
    else
    {
        return SENSOR_ERROR_ARGS;
    }

    return driver->write_reg(driver,buf, 1);
}


/*
 * @param index[0-2] ~ LED[0-2]
 * @param mode - combine of MAX_CURRENT_SETTING_t | OPERATING_MODE_t |
 * FADE_IN_STATE_t| FADE_OUT_STATE_t
*/
int aw2013_get_control_mode(aw2013_dev_t *dev, LED_INDEX_t index, uint8_t *mode)
{
    DEV_ASSERT(dev);
    int ret;
    uint8_t buf[] = {0, 0};
    sensor_serial_if_t *driver = dev->driver;
    
    if(index == 0)
        buf[0] = AW_REG_LED0_MODE_CONTROL;
    else if(index == 1)
        buf[0] = AW_REG_LED1_MODE_CONTROL;
    else if(index == 2)
        buf[0] = AW_REG_LED2_MODE_CONTROL;
    else
    {
        return SENSOR_ERROR_ARGS;
    }

    ret = driver->read_reg(driver,buf, 1);
    *mode = buf[1];
    
    return ret;
}

/**
 * @brief set brightness of led
 * @param led - range(0~2)
 * @param brightness - range(0~255), 0 is dark
*/
int aw2013_set_brightness(aw2013_dev_t *dev, LED_INDEX_t index, uint8_t brightness)
{
    DEV_ASSERT(dev);

    uint8_t buf[] = {0, brightness};
    sensor_serial_if_t *driver = dev->driver;
    if(index == 0)
        buf[0] = AW_REG_LED0_PWM_SETTING;
    else if(index == 1)
        buf[0] = AW_REG_LED1_PWM_SETTING;
    else if(index == 2)
        buf[0] = AW_REG_LED2_PWM_SETTING;
    else
    {
        return SENSOR_ERROR_ARGS;
    }

    return driver->write_reg(driver,buf, 1);
}


int aw2013_get_brightness(aw2013_dev_t *dev, LED_INDEX_t index, uint8_t *brightness)
{
    DEV_ASSERT(dev);
    
    int ret = SENSOR_SUCCESS;
    uint8_t buf[] = {0, 0};
    sensor_serial_if_t *driver = dev->driver;
    if(index == 0)
        buf[0] = AW_REG_LED0_PWM_SETTING;
    else if(index == 1)
        buf[0] = AW_REG_LED1_PWM_SETTING;
    else if(index == 2)
        buf[0] = AW_REG_LED2_PWM_SETTING;
    else
    {
        return SENSOR_ERROR_ARGS;
    }

    ret = driver->read_reg(driver,buf, 1);
    *brightness = buf[1];
    
    return ret;
}


int aw2013_set_timing_control0(aw2013_dev_t *dev, LED_INDEX_t index, uint8_t t1, uint8_t t2)
{
    DEV_ASSERT(dev);

    uint8_t buf[] = {0, t1 | t2};
    sensor_serial_if_t *driver = dev->driver;
    if(index == 0)
        buf[0] = AW_REG_T0_TIMING_CONTROL0;
    else if(index == 1)
        buf[0] = AW_REG_T0_TIMING_CONTROL1;
    else if(index == 2)
        buf[0] = AW_REG_T0_TIMING_CONTROL2;
    else
    {
        return SENSOR_ERROR_ARGS;
    }

    return driver->write_reg(driver,buf, 1);
}



int aw2013_set_timing_control1(aw2013_dev_t *dev, LED_INDEX_t index, uint8_t t3, uint8_t t4)
{
    DEV_ASSERT(dev);

    uint8_t buf[] = {0, t3 | t4};
    sensor_serial_if_t *driver = dev->driver;
    if(index == 0)
        buf[0] = AW_REG_T1_TIMING_CONTROL0;
    else if(index == 1)
        buf[0] = AW_REG_T1_TIMING_CONTROL1;
    else if(index == 2)
        buf[0] = AW_REG_T1_TIMING_CONTROL2;
    else
    {
        return SENSOR_ERROR_ARGS;
    }

    return driver->write_reg(driver,buf, 1);
}

int aw2013_set_timing_control2(aw2013_dev_t *dev, LED_INDEX_t index, uint8_t t0, uint8_t repeat)
{
    DEV_ASSERT(dev);

    uint8_t buf[] = {0, t0 | repeat};
    sensor_serial_if_t *driver = dev->driver;
    if(index == 0)
        buf[0] = AW_REG_T2_TIMING_CONTROL0;
    else if(index == 1)
        buf[0] = AW_REG_T2_TIMING_CONTROL1;
    else if(index == 2)
        buf[0] = AW_REG_T2_TIMING_CONTROL2;
    else
    {
        return SENSOR_ERROR_ARGS;
    }

    return driver->write_reg(driver,buf, 1);
}


int aw2013_init_default(aw2013_dev_t *dev)
{
    int ret = SENSOR_SUCCESS;

    if(!aw2013_check_id(dev))
    {
        return SENSOR_ERROR_CHECK_ID;
    }
    
    ret |= aw2013_set_global_control(dev, LED0_INT_DISABLE | LED0_INT_DISABLE | 
                                     LED0_INT_DISABLE | LED_FUNCTION_ENABLE);
    ret |= aw2013_set_control_mode(dev, AW_LED0, IMAX_15MA | 
                                   PWM_CONTROL_MODE | FADE_ID_ENABLE | FADE_OUT_ENABLE);
    ret |= aw2013_set_control_mode(dev, AW_LED1, IMAX_15MA | 
                                   PWM_CONTROL_MODE | FADE_ID_ENABLE | FADE_OUT_ENABLE);
    ret |= aw2013_set_control_mode(dev, AW_LED2, IMAX_15MA | 
                                   PWM_CONTROL_MODE | FADE_ID_ENABLE | FADE_OUT_ENABLE);
    
    ret |= aw2013_set_brightness(dev, AW_LED0, 50);
    ret |= aw2013_set_brightness(dev, AW_LED1, 100);
    ret |= aw2013_set_brightness(dev, AW_LED2, LED_MAX_BRIGHTNESS);
    
    ret |=aw2013_set_timing_control0(dev, AW_LED0, 
                                     LED_TIMING_T1_N_13S(2), LED_TIMING_T2_N_13S(5));
    ret |= aw2013_set_timing_control0(dev, AW_LED1, 
                                      LED_TIMING_T1_N_13S(0), LED_TIMING_T2_N_13S(2));
    ret |= aw2013_set_timing_control0(dev, AW_LED2, 
                                      LED_TIMING_T1_N_13S(3), LED_TIMING_T2_N_13S(1));
    
    ret |= aw2013_set_timing_control1(dev, AW_LED0, 
                                      LED_TIMING_T3_N_13S(0), LED_TIMING_T4_N_13S(1));
    ret |= aw2013_set_timing_control1(dev, AW_LED1, 
                                      LED_TIMING_T3_N_13S(2), LED_TIMING_T4_N_13S(3));
    ret |= aw2013_set_timing_control1(dev, AW_LED2, 
                                      LED_TIMING_T3_N_13S(4), LED_TIMING_T4_N_13S(5));
    
    ret |= aw2013_set_timing_control2(dev, AW_LED0, 
                                      BREATH_CYCLE_DELAY_TIME_N13S(0), INFINITE_LOOP);
    ret |= aw2013_set_timing_control2(dev, AW_LED1, 
                                      BREATH_CYCLE_DELAY_TIME_N13S(1), REPEAT_TIMES(2));
    ret |= aw2013_set_timing_control2(dev, AW_LED2, 
                                      BREATH_CYCLE_DELAY_TIME_N13S(2), REPEAT_TIMES(10));

    return ret;
}




