#include "epd_init.h"
#include "delay.h"

/**
 * @brief       初始化EPD端口
 * @param       无
 * @retval      无
 */
void EPD_GPIOInit(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(EPD_RES_GPIO_CLK|EPD_DC_GPIO_CLK|EPD_BUSY_GPIO_CLK,ENABLE);

    GPIO_InitStructure.GPIO_Pin=EPD_RES_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(EPD_RES_GPIO_PORT,&GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin=EPD_DC_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(EPD_DC_GPIO_PORT,&GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin=EPD_BUSY_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IN_FLOATING;
    GPIO_Init(EPD_BUSY_GPIO_PORT,&GPIO_InitStructure);
}

/**
 * @brief       向墨水屏写寄存器命令
 * @param       reg: 要写的命令
 * @retval      无
 */
void EPD_WR_REG(uint8_t reg)
{
    EPD_DC_Clr();
    BSP_SPI_WR_Bus(reg);
    EPD_DC_Set();
}

/**
 * @brief       向墨水屏写一个字节数据
 * @param       dat: 要写的数据
 * @retval      无
 */
void EPD_WR_DATA8(uint8_t dat)
{
    EPD_DC_Set();
    BSP_SPI_WR_Bus(dat);
    EPD_DC_Set();
}

/**
 * @brief       EPD读忙
 * @param       无
 * @retval      无
 * @note        BUSY 低电平为忙状态 高电平为空闲状态
 */
void EPD_READBUSY(void)
{
    while (1)
    {
        if (EPD_ReadBUSY == 1)
        {
            break;
        }
    }
}

/**
 * @brief       EPD硬件复位
 * @param       无
 * @retval      无
 * @note        退出休眠时需要进行一次硬件复位
 */
void EPD_HW_RESET(void)
{
    EPD_RES_Set();
    delay_ms(100);
    EPD_RES_Clr();
    delay_ms(100);
    EPD_RES_Set();
    delay_ms(100);
}

/**
 * @brief       EPD进入休眠模式
 * @param       无
 * @retval      无
 * @note        不同休眠模式下功耗不同 默认配置模式1 保留RAM数据
 */
void EPD_Sleep(void)
{
    EPD_WR_REG(0x02); // 0x02 Power OFF 
    EPD_WR_DATA8(0x00);
    EPD_READBUSY();

    EPD_WR_REG(0x07); // 0x07 Deep_Sleep 
    EPD_WR_DATA8(0xA5);
}

/**
 * @brief       EPD全刷模式更新显示
 * @param       无
 * @retval      无
 */
void EPD_Update(void)
{
    EPD_WR_REG(0X04); // power on 
    delay_ms(50);
    EPD_READBUSY();

    EPD_WR_REG(0x12); // 0x12 Display Refresh 
    EPD_WR_DATA8(0x00);
    EPD_READBUSY();
}

/**
 * @brief       EPD全屏颜色填充
 * @param       color：填充颜色值
 * @retval      无
 */
void EPD_All_Fill(uint8_t color)
{
    uint8_t dat;
    uint32_t i;
    EPD_WR_REG(0x10); /* 写RAM指令 具体参考SSD1680 datasheet */
    switch (color)
    {
    case 0x00:
        dat = 0x00;
        break;
    case 0x01:
        dat = 0x55;
        break;
    case 0x02:
        dat = 0xAA;
        break;
    case 0x03:
        dat = 0xFF;
    default:
        break;
    }
    for (i = 0; i < ALLSCREEN_BYTES; i++)
    {
        EPD_WR_DATA8(dat);
    }
    EPD_READBUSY();
}

/**
 * @brief       EPD全屏显示图像
 * @param       ImageBW：图像数组名
 * @retval      无
 */
void EPD_DisplayImage(const uint8_t *ImageBW)
{
    uint8_t temp, dataH1, dataH2, dataL1, dataL2, dat;
    uint32_t i;
    EPD_WR_REG(0x10);
    for (i = 0; i < ALLSCREEN_BYTES; i++)
    {
        temp = ImageBW[i];
        dataH1 = (temp >> 6 & 0x03) << 6;
        dataH2 = (temp >> 4 & 0x03) << 4;
        dataL1 = (temp >> 2 & 0x03) << 2;
        dataL2 = (temp & 0x03);
        dat = dataH1 | dataH2 | dataL1 | dataL2;
        EPD_WR_DATA8(dat);
    }
}

/**
 * @brief       初始化EPD
 * @param       无
 * @retval      无
 */
void EPD_Init(void)
{
    EPD_GPIOInit(); /* 初始化EPD信号线 */
    
    EPD_HW_RESET();/* 执行硬件及软件复位 EPD */
    EPD_READBUSY();

    EPD_WR_REG(0x00);   //0x00  
    EPD_WR_DATA8(0x0B);  // bit5=1 ModeB
    EPD_WR_DATA8(0x29);  
    EPD_READBUSY(); //??driver ic??

    EPD_WR_REG(0x06);//0x06
    EPD_WR_DATA8(0x0F);
    EPD_WR_DATA8(0x8B);
    EPD_WR_DATA8(0x93);
    EPD_WR_DATA8(0xA4);//C1 A6

    EPD_WR_REG(0x61);
    EPD_WR_DATA8(0x03);// Source Line 
    EPD_WR_DATA8(0x20);
    EPD_WR_DATA8(0x02);// Gate Line 
    EPD_WR_DATA8(0xA8);
    EPD_READBUSY();//检测driver ic状态

    EPD_WR_REG(0x50);
    EPD_WR_DATA8(0x37);

    EPD_WR_REG(0x30);
    EPD_WR_DATA8(0x08);

    EPD_WR_REG(0x62);
    EPD_WR_DATA8(0x76);
    EPD_WR_DATA8(0x76);
    EPD_WR_DATA8(0x76);
    EPD_WR_DATA8(0x5A);
    EPD_WR_DATA8(0x9D);
    EPD_WR_DATA8(0x8A);
    EPD_WR_DATA8(0x76);
    EPD_WR_DATA8(0x62);

    EPD_WR_REG(0xE3);//0xE3
    EPD_WR_DATA8(0x22);

    EPD_WR_REG(0xE0);//复位后 //eink专用 不方便解释
    EPD_WR_DATA8(0x10);

    EPD_WR_REG(0xE7);
    EPD_WR_DATA8(0xA4); //设置BTST最后一位 A6

    EPD_WR_REG(0xE9);
    EPD_WR_DATA8(0x01);
}






