/*
 * awinic AW20108 / AW20072 / AW20054 / AW20036 LED Matrix Driver
 */

#ifndef AW20X_LED_MATRIX_H
#define AW20X_LED_MATRIX_H



#include <stdint.h>

#include "../comm/i2c.h"



#define AW20X_INIT_DELAY()      { uint16_t zz = 1000; while(zz--); }
                                            // burn cycles for ~200us

#define AW20X_MAX_COLS          9
#define AW20X_MAX_ROWS          12

#define AW20X_MAX_LEDON_BITS    6

#define AW20X_ADDR_SCL          0x38        // AD pin tied to SCL
#define AW20X_ADDR_SDA          0x39        // AD pin tied to SDA
#define AW20X_ADDR_GND          0x3A        // AD pin tied to GND
#define AW20X_ADDR_VDD          0x3B        // AD pin tied to VDD

#define AW20X_CONF_IMAX_MASK    0xf0        // 7:4
#define AW20X_CONF_IMAX_OFFSET  4           // 7:4
#define AW20X_CONF_ADDR_MASK    0x03        // 1:0
#define AW20X_CONF_ADDR_OFFSET  0           // 1:0

#define AW20X_CONF_USE_FADEDIM  0x08        // aw20x.fade now becomes fadedim; updates are done with FADEDIM page
                                            // this mode uses 2 bytes per LED; dim as byte 0, fade as byte 1
#define AW20X_CONF_USE_EXPEN    0x04        // sets GCCR.EXPEN=1; fade is now only 6 bits (not yet implemented)

#define AW20X_PAGE_MASK         0x07

#define AW20X_STATE_PAGE_MASK   AW20X_PAGE_MASK
#define AW20X_STATE_SLEEP_MASK  0x80


#define AW20X_PAGE0_CONFIG      0x00        // function register
#define AW20X_PAGE1_DIM         0x01        // 5:0 dim;     8 bits per LED
#define AW20X_PAGE2_FADE        0x02        // 7:0 fade;    8 bits per LED
#define AW20X_PAGE3_PATTERN     0x03        // 1:0 pattern; 8 bits per LED
#define AW20X_PAGE4_DIMFADE     0x04        // 13:8 dim, 7:0 fade; 16 bits per LED
#define AW20X_PAGE5_DFP         0x05        // 15:14 pat, 13:8 dim, 7:0 fade; 16 bits per LED

#define AW20X_REG_IDR           0x00        // R    7:0 chip ID                       {0x18}
#define AW20X_REG_SLPCR         0x01        // RW   7   sleep                         {0x80}
#define AW20X_REG_RSTR          0x02        //  W   7:0 SW_RSTN (?)
#define AW20X_REG_GCCR          0x03        // RW   7:3 IMAX(7:4), ALLON, -, -, EXPEN {0x10}
#define AW20X_REG_FCD           0x04        //  W   0   FCDE (fast clear display enable)
#define AW20X_REG_CLKSYS        0x05        // RW   1:0 CLK_IO, CLK_SEL
#define AW20X_REG_FLTCFG1       0x09        // RW   5:0 UVLOPE, OTPE, UVIE, OTIE, UVLOE, OTE
#define AW20X_REG_FLTCFG2       0x0a        // RW   3:2 UVTH
#define AW20X_REG_ISRFLT        0x0b        // RW   5:0 PAT2IS, PAT1IS, PAT0IS, -, -, UVLOIS, OTIS
#define AW20X_REG_LEDON0        0x31        // W    5:0 ON0:ON5, same pattern through to LEDON17 (0x42)
#define AW20X_REG_PATCR         0x43        // RW   6:0 PAT2IE, PAT1IE, PAT0IE, -, PAT2EN, PAT1EN, PAT0EN
#define AW20X_REG_FADEH0        0x44        // RW   7:0 FADEH0
#define AW20X_REG_FADEH1        0x45
#define AW20X_REG_FADEH2        0x46
#define AW20X_REG_FADEL0        0x47
#define AW20X_REG_FADEL1        0x48
#define AW20X_REG_FADEL2        0x49        // RW   7:0 FADEL2
#define AW20X_REG_PAT0T0        0x4a        // RW   7:0 T1[4], T2[4]
#define AW20X_REG_PAT0T1        0x4b        // RW   7:0 T3[4], T4[4]
#define AW20X_REG_PAT0T2        0x4c        // RW   7:0 LE[2], LB[2], LT(11:8)[4]
#define AW20X_REG_PAT0T3        0x4d        // RW   7:0 LT(7:0)
#define AW20X_REG_PAT1T0        0x4e
#define AW20X_REG_PAT1T1        0x4f
#define AW20X_REG_PAT1T2        0x50
#define AW20X_REG_PAT1T3        0x51
#define AW20X_REG_PAT2T0        0x52
#define AW20X_REG_PAT2T1        0x53
#define AW20X_REG_PAT2T2        0x54
#define AW20X_REG_PAT2T3        0x55
#define AW20X_REG_PAT0CFG       0x56        // RW   2:0 SWITCH, RAMPE, PATMD
#define AW20X_REG_PAT1CFG       0x57
#define AW20X_REG_PAT2CFG       0x58
#define AW20X_REG_PATGO         0x59        // RW   6:0 PAT2ST, PAT1ST, PAT0ST, -, RUN2, RUN1, RUN0
#define AW20X_REG_SIZE          0x80        // RW   3:0 SWSEL
#define AW20X_REG_PAGE          0xf0        // RW   2:0 page select, 0-5; available from all pages

#define AW20X_IDR_ID            0x18        // value for all chips in this series

#define AW20X_SLPCR_SLEEP       0x01        // sleep mode (default is HIGH / asleep)

#define AW20X_RSTR_SW_RSTN      0x01        // write value to soft reset the chip

#define AW20X_GCCR_IMAX         0xf0        // global current setting (default 20mA)
#define AW20X_GCCR_ALLON        0x08        // 0=normal, 1=force all on
#define AW20X_GCCR_EXPEN        0x01        // 0=fade is linear 8-bit, 1=fade is exponential 6-bit

#define AW20X_FCD_FCDE          0x01        // write value to clear display (DS doesn't specify; is this a blanker?)

#define AW20X_CLKSYS_CLK_IO     0x02        // 0=no clk output, 1=clk output on (output) CLKIO pin
#define AW20X_CLKSYS_CLK_SEL    0x01        // 0=internal 4MHz, 1=use clk on (input) CLKIO pin

#define AW20X_FLTCFG1_UVLOPE    0x20        // 1=enable UVLO protection;     chip sets SLPCR.SLEEP when ISRFLT.UVLOIS=1
#define AW20X_FLTCFG1_OTPE      0x10        // 1=enable overtemp protection; chip sets SLPCR.SLEEP when ISRFLT.UVLOIS=1
#define AW20X_FLTCFG1_UVIE      0x08        // 1=UVLO interrupt enable
#define AW20X_FLTCFG1_OTIE      0x04        // 1=overtemp interrupt enable
#define AW20X_FLTCFG1_UVLOE     0x02        // 1=enable UVLO detect
#define AW20X_FLTCFG1_OTE       0x01        // 1=enable overtemp detect

#define AW20X_FLTCFG1_UVTH_2V0  (0x00 << 2) // UVLO threshold voltage
#define AW20X_FLTCFG1_UVTH_2V1  (0x01 << 2) // UVLO threshold voltage
#define AW20X_FLTCFG1_UVTH_2V2  (0x02 << 2) // UVLO threshold voltage
#define AW20X_FLTCFG1_UVTH_2V3  (0x03 << 2) // UVLO threshold voltage

#define AW20X_ISRFLT_PAT2IS     0x40        // pattern controller 2 interrupt (finished breath loop)
#define AW20X_ISRFLT_PAT1IS     0x20        // pattern controller 1 interrupt (finished breath loop)
#define AW20X_ISRFLT_PAT0IS     0x10        // pattern controller 0 interrupt (finished breath loop)
#define AW20X_ISRFLT_UVLOIS     0x02        // 0=normal, 1=UVLO detected
#define AW20X_ISRFLT_OTIS       0x01        // 0=normal, 1=overtemp detected

// todo: fill in all values from PATCR onward



#define AW20X_SOFT_RESET        AW20X_RSTR_SW_RSTN

enum aw20x_imax {
    AW20X_IMAX_10MA     = 0x00,
    AW20X_IMAX_20MA     = 0x10,
    AW20X_IMAX_30MA     = 0x20,
    AW20X_IMAX_40MA     = 0x30,
    AW20X_IMAX_60MA     = 0x40,
    AW20X_IMAX_80MA     = 0x50,
    AW20X_IMAX_120MA    = 0x60,
    AW20X_IMAX_160MA    = 0x70,
    AW20X_IMAX_3_3MA    = 0x80,
    AW20X_IMAX_6_7MA    = 0x90,
    AW20X_IMAX_10MA_2   = 0xa0,
    AW20X_IMAX_13_3MA   = 0xb0,
    AW20X_IMAX_20MA_2   = 0xc0,
    AW20X_IMAX_26_7MA   = 0xd0,
    AW20X_IMAX_40MA_2   = 0xe0,
    AW20X_IMAX_53_3MA   = 0xf0
};

enum aw20x_size {
    AW20X_SIZE_1COL     = 0,
    AW20X_SIZE_2COL,
    AW20X_SIZE_3COL,
    AW20X_SIZE_4COL,
    AW20X_SIZE_5COL,
    AW20X_SIZE_6COL,
    AW20X_SIZE_7COL,
    AW20X_SIZE_8COL,
    AW20X_SIZE_9COL
};



#ifdef SOFT_I2C_MASTER
#define AW20X_I2C_busy()                        (0)
#define AW20X_I2C_writereg(adr, reg, buf, siz)  i2c_write_reg8(adr, reg, buf, siz)
#else
#define AW20X_I2C_busy()                        (0)
#define AW20X_I2C_writereg(adr, reg, buf, siz)  i2c_write_addr1b(adr, reg, buf, siz);
#endif



typedef struct AW20x {
    uint8_t addr;
    uint8_t config;         // settings for the chip
    uint8_t state;          // keeps track of active page, and high bit is set if asleep
    uint8_t cols;           // highest column used by application, 1-9
    uint8_t rows;           // highest row used by application,    1-12
    uint8_t pad[3];
    uint8_t *fade;          // led buffer location for FADE (required), of size cols+rows
    uint8_t *gain;          // led buffer location for GAIN (optional), of size cols+rows
} AW20x;



void aw20x_init(struct AW20x *aw, uint8_t addr, uint8_t cols, uint8_t rows, uint8_t imax);

void aw20x_set_sleep(struct AW20x *aw, uint8_t sleep);
void aw20x_set_imax(struct AW20x *aw, uint8_t imax);

void aw20x_set_fade(struct AW20x *aw);
void aw20x_set_dim_global(struct AW20x *aw, uint8_t dim);

void aw20x_led_enable_range(struct AW20x *aw, uint8_t first, uint8_t last);



#endif  /* AW02X_LED_MATRIX_H */
