/*
 * Copyright (c) 2020 Great Master Wu. All rights reserved.
 * Author    Date          ChangeLog
 * Master    2021-03-25    Initialize version
 */
#ifndef __AW2013_H__
#define __AW2013_H__
#include "platform_if.h"
#include "sensor_type.h"


#define AW2013_DEV_7BIT_ADDR        (0x45)

#define AW_REG_RESET                (0x00)
#define AW_RESET_CMD                (0x55)
#define AW2013_CHIPID               (0x33)

typedef enum
{
    AW_LED0 = 0,
    AW_LED1,
    AW_LED2,
}LED_INDEX_t;

/*  Global Control Register, GCR  */
#define AW_REG_GLOBAL_CONTROL       (0x01)

// LED function enable. enabled when set to 1
#define LED_FUNCTION_ENABLE_POS     (0)
#define LED_FUNCTION_ENABLE_MASK    (1 << LED_FUNCTION_ENABLE_POS)

#define LED0_INT_ENABLE_POS         (5)
#define LED0_INT_ENABLE_MASK        (1 << LED0_INT_ENABLE_POS)

#define LED1_INT_ENABLE_POS         (6)
#define LED1_INT_ENABLE_MASK        (1 << LED1_INT_ENABLE_POS)

// LED2 interrupt enable,enabled when set to 1
#define LED2_INT_ENABLE_POS         (7)
#define LED2_INT_ENABLE_MASK        (1 << LED2_INT_ENABLE_POS)

typedef enum
{
    LED2_INT_DISABLE = (0 << LED2_INT_ENABLE_POS),
    LED2_INT_ENABLE  = (1 << LED2_INT_ENABLE_POS),
}LIE2_STATE_t;


typedef enum
{
    LED1_INT_DISABLE = (0 << LED1_INT_ENABLE_POS),
    LED1_INT_ENABLE  = (1 << LED1_INT_ENABLE_POS),
}LIE1_STATE_t;

typedef enum
{
    LED0_INT_DISABLE = (0 << LED0_INT_ENABLE_POS),
    LED0_INT_ENABLE  = (1 << LED0_INT_ENABLE_POS),
}LIE0_STATE_t;

typedef enum
{
    LED_FUNCTION_DISABLE = (0 << LED_FUNCTION_ENABLE_POS),
    LED_FUNCTION_ENABLE  = (1 << LED_FUNCTION_ENABLE_POS),
}LED_FUNCTION_STATE_t;

/*  Interrupt Status Register, ISR   */
#define AW_REG_INT_STATUS           (0x02)
#define LIS2_INDICATOR_POS          (7)
#define LIS2_INDICATOR_MASK         (1 << LIS2_INDICATOR_POS)

#define LIS1_INDICATOR_POS          (6)
#define LIS1_INDICATOR_MASK         (1 << LIS1_INDICATOR_POS)

#define LIS0_INDICATOR_POS          (5)
#define LIS0_INDICATOR_MASK         (1 << LIS0_INDICATOR_POS)

#define PUIS_INDICATOR_POS          (4)
#define PUIS_INDICATOR_MASK         (1 << PUIS_INDICATOR_POS)


/* LED Mode Control Register, LCFG0~2 */
#define AW_REG_LED0_MODE_CONTROL    (0x31)
#define AW_REG_LED1_MODE_CONTROL    (0x32)
#define AW_REG_LED2_MODE_CONTROL    (0x33)

/*
 00:0mA (default)
 01:5mA
 10:10mA
 11:15mA
*/
#define IMAX_POS                    (0)
#define IMAX_MASK                   (0x03 << IMAX_POS)

/*
 Operating mode selection bit
 0: PWM control mode
 1: One short programming mode
*/
#define OPERATING_MD_POS            (4)
#define OPERATING_MD_MASK           (0x01 << OPERATING_MD_POS)

/* Fade in effect enable. If current brightness level is lower than the 
 * value set into PWMx, the controller will brighten the LED smoothly 
 * when this bit is set to 1, This bit is only valid when LCFGx.MD=0 */
#define FADE_IN_POS                 (5)
#define FADE_IN_MASK                (1 << FADE_IN_POS)

/* 
 * Fade out effect enable. If current brightness level is higher than 
 * the value set into PWMx, the controller will darken the LED smoothly 
 * when this bit is set to 1 This bit is only valid when LCFGx.MD=0
*/
#define FADE_OUT_POS                (6)
#define FADE_OUT_MASK               (1 << FADE_OUT_POS)

typedef enum
{
    IMAX_0MA  = (0 << IMAX_POS),
    IMAX_5MA  = (1 << IMAX_POS),
    IMAX_10MA = (2 << IMAX_POS),
    IMAX_15MA = (3 << IMAX_POS),
}MAX_CURRENT_SETTING_t;


typedef enum
{
    PWM_CONTROL_MODE       = (0 << OPERATING_MD_POS),
    ONE_SHORT_PROGRAM_MODE = (1 << OPERATING_MD_POS),
}OPERATING_MODE_t;

typedef enum
{
    FADE_ID_DISABLE = (0 << FADE_IN_POS),
    FADE_ID_ENABLE  = (1 << FADE_IN_POS),
}FADE_IN_STATE_t;


typedef enum
{
    FADE_OUT_DISABLE = (0 << FADE_OUT_POS),
    FADE_OUT_ENABLE  = (1 << FADE_OUT_POS),
}FADE_OUT_STATE_t;

/* PWM Setting Register, PWM0~2 */
#define AW_REG_LED0_PWM_SETTING     (0x34)
#define AW_REG_LED1_PWM_SETTING     (0x35)
#define AW_REG_LED2_PWM_SETTING     (0x36)

#define LED_DARK                    (0x00)
#define LED_MAX_BRIGHTNESS          (0xFF)


/* LED Timing Control Register0, LEDxT0 */
#define AW_REG_T0_TIMING_CONTROL0   (0x37)
#define AW_REG_T0_TIMING_CONTROL1   (0x3A)
#define AW_REG_T0_TIMING_CONTROL2   (0x3D)
#define LED_TIMING_T1_POS           (4)
#define LED_TIMING_T1_MASK          (7 << 4)
#define LED_TIMING_T2_POS           (0)
#define LED_TIMING_T2_MASK          (6 << LED_TIMING_T2_POS)
/* Set the Tn period in breath cycle. 8 levels can be selected. */
/* the time = (n+1)*0.13 */
#define LED_TIMING_T1_N_13S(n)      (((n) << LED_TIMING_T1_POS) & LED_TIMING_T1_MASK)
#define LED_TIMING_T2_N_13S(n)      (((n) << LED_TIMING_T2_POS) & LED_TIMING_T2_MASK)


#define AW_REG_T1_TIMING_CONTROL0   (0x38)
#define AW_REG_T1_TIMING_CONTROL1   (0x3B)
#define AW_REG_T1_TIMING_CONTROL2   (0x3E)
#define LED_TIMING_T3_POS           (4)
#define LED_TIMING_T3_MASK          (7 << LED_TIMING_T3_POS)
#define LED_TIMING_T4_POS           (0)
#define LED_TIMING_T4_MASK          (6 << LED_TIMING_T4_POS)
/* Set the Tn period in breath cycle. 8 levels can be selected. */
/* the time = (n+1)*0.13 */
#define LED_TIMING_T3_N_13S(n)      (((n) << LED_TIMING_T3_POS) & LED_TIMING_T3_MASK)
#define LED_TIMING_T4_N_13S(n)      (((n) << LED_TIMING_T4_POS) & LED_TIMING_T4_MASK)


#define AW_REG_T2_TIMING_CONTROL0   (0x39)
#define AW_REG_T2_TIMING_CONTROL1   (0x3C)
#define AW_REG_T2_TIMING_CONTROL2   (0x3F)
#define BREATH_CYCLE_DELAY_TIME_POS       (4)
#define BREATH_CYCLE_DELAY_TIME_MASK      (8 << BREATH_CYCLE_DELAY_TIME_POS)
#define BREATH_CYCLE_DELAY_TIME_N13S(n)   (((n) << BREATH_CYCLE_DELAY_TIME_POS) & BREATH_CYCLE_DELAY_TIME_MASK)

#define INFINITE_LOOP                (0)
#define REPEAT_TIMES_MASK            (0x0F)
// max 15 times
#define REPEAT_TIMES(n)              (n)&REPEAT_TIMES_MASK


typedef struct aw2013_dev{
    sensor_serial_if_t *driver;
    char *name;
}aw2013_dev_t;

bool aw2013_check_id(aw2013_dev_t *dev);


int aw2013_reset(aw2013_dev_t *dev);

int aw2013_set_global_control(aw2013_dev_t *dev, uint8_t state);

/* default enter sleep after power up */
int aw2013_enter_sleep(aw2013_dev_t *dev);

int aw2013_get_global_control(aw2013_dev_t *dev, uint8_t *state);

int aw2013_get_interrupt_status(aw2013_dev_t *dev, uint8_t *status);

int aw2013_set_control_mode(aw2013_dev_t *dev, LED_INDEX_t index, uint8_t mode);

int aw2013_get_control_mode(aw2013_dev_t *dev, LED_INDEX_t index, uint8_t *mode);

int aw2013_set_brightness(aw2013_dev_t *dev, LED_INDEX_t index, uint8_t brightness);

int aw2013_get_brightness(aw2013_dev_t *dev, LED_INDEX_t index, uint8_t *brightness);

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

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

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

int aw2013_init_default(aw2013_dev_t *dev);
#endif

