#ifndef _EPD_H_
#define _EPD_H_
#include <inttypes.h>
#include "driver/gpio.h"


#define SOFTWARE_SPI_ENABLE 0

#define QUICK_DISPLAY  0     //快刷

#define HARDWARE_SPI        1
#if HARDWARE_SPI    

#include "driver/spi_master.h"

#define SPI_MAX_LEN 3200

#define EPD_HOST    SPI2_HOST

#define PIN_SPI_MOSI 45
#define PIN_SPI_CLK  48

#define PIN_L_CS   39
#define PIN_L_DC   40
#define PIN_L_RST  41
#define PIN_L_BUSY  42

#define PIN_R_CS   47
#define PIN_R_DC   21
#define PIN_R_RST  14
#define PIN_R_BUSY  13

#if !SOFTWARE_SPI_ENABLE //
#define PIN_EPD_OUTPUT      ((1ULL<<PIN_L_CS)|(1ULL<<PIN_L_DC)|(1ULL<<PIN_L_RST)|(1ULL<<PIN_R_CS)|(1ULL<<PIN_R_DC)|(1ULL<<PIN_R_RST))
#else
#define PIN_EPD_OUTPUT      ((1ULL<<PIN_SPI_MOSI)|(1ULL<<PIN_SPI_CLK)|(1ULL<<PIN_L_CS)|(1ULL<<PIN_L_DC)|(1ULL<<PIN_L_RST)|(1ULL<<PIN_R_CS)|(1ULL<<PIN_R_DC)|(1ULL<<PIN_R_RST))
#endif


#define PIN_EPD_INPUT        ((1ULL<<PIN_L_BUSY)|(1ULL<<PIN_R_BUSY))


typedef enum {
    SCREEN_LEFT     = 1,
    SCREEN_RIGHT    = 2,
}screen_t;


typedef struct {
    uint8_t cmd;
    uint8_t data[16];
    uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds.
} epd_init_cmd_t;


extern spi_device_handle_t epd_spi;

void epd_write_cmd(screen_t screen, unsigned char command,bool keep_cs_active);
void epd_write_data(screen_t screen, const uint8_t *data, int len);
void epd_init(void);
void epd_display(screen_t screen,const unsigned char* picData);
void epd_cache(screen_t screen,const unsigned char* picData);
void epd_display_partal(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend,
                         screen_t screen,const unsigned char* picData);
void epd_partial_cache(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend,
                         screen_t screen,const unsigned char* picData);


                         void epd_partial_cache1(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend,
                         screen_t screen,const unsigned char* picData);
void epd_powerOn_refresh(screen_t screen);


void epd_init_cmd(screen_t screen);

void epd_sleep(screen_t screen);


bool epd_check_status(screen_t screen);
void epd_refresh(screen_t screen);


void epd_check_power_off(screen_t screen);
void epd_check_power_on(screen_t screen);


void epd_cache_quick_full_screen_refresh(screen_t screen,const unsigned char* old,const unsigned char* new);

void epd_cache_quick_partial_screen_refresh(screen_t screen,uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend,const unsigned char* old,const unsigned char* new);

unsigned int compressRLE(uint8_t *input, unsigned int size, uint8_t *output);
// 解压函数
unsigned int decompressRLE(uint8_t *input, unsigned int size, uint8_t *output);

void deepsleep_epd_check_status(screen_t screen);

void deepsleep_epd_powerOn_refresh_sleep(screen_t screen);



bool epd_cache_quick(screen_t screen,const unsigned char* old,const unsigned char* new);
void epd_powerOn_refresh_sleep(screen_t screen);

bool left_refresh_timer_isActive();
bool right_refresh_timer_isActive();


#else /*HARDWARE_SPI*/




#define LOW_LEVEL       0
#define HIGH_LEVEL      1

struct EPD_INFO_SET
{
    char* epd_name;
    uint8_t sclk_pin;
    uint8_t sda_pin;
    uint8_t busy_pin;
    uint8_t res_pin;
    uint8_t dc_pin;
    uint8_t cs_pin;
};

#define epd_set_level(EPD_PIN, LEVEL)     gpio_set_level(EPD_PIN, LEVEL)
#define epd_get_level(EPD_PIN)               gpio_get_level(EPD_PIN)



void epd_screen_init(struct EPD_INFO_SET* epd_pin_set);
void epd_pin_init(struct EPD_INFO_SET* epd_pin_set);
void epd_spi_write(struct EPD_INFO_SET* epd_pin_set, unsigned char value);
void epd_write_cmd(struct EPD_INFO_SET* epd_pin_set, unsigned char command);
void epd_write_data(struct EPD_INFO_SET* epd_pin_set, unsigned char command);
void epd_init(struct EPD_INFO_SET* epd_pin_set);
void epd_check_status(struct EPD_INFO_SET* epd_pin_set);
void epd_refresh(struct EPD_INFO_SET* epd_pin_set);
void epd_sleep(struct EPD_INFO_SET* epd_pin_set);
void epd_clear_black(struct EPD_INFO_SET* epd_pin_set);
void epd_clear_write(struct EPD_INFO_SET* epd_pin_set);




void epd_display(struct EPD_INFO_SET* epd_pin_set,const unsigned char* picData);


void epd_display_partal(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend,struct EPD_INFO_SET* epd_pin_set,const unsigned char* picData);

void epd_cache(struct EPD_INFO_SET* epd_pin_set,const unsigned char* picData);
void epd_partial_cache(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend,struct EPD_INFO_SET* epd_pin_set,const unsigned char* picData);
void epd_powerOn_refresh(struct EPD_INFO_SET* epd_pin_set);

#endif /*HARDWARE_SPI*/

#endif/*_EPD_H_*/
