/*******************************************************************************
*
*
* File:         demo_hal_dsi_tx.c
* Description：  dsi_tx demo源文件
* Version：      V0.1
* Date:         2023-07-27
* Author：       zzf
 *******************************************************************************/

/*******************************************************************************
* 1.Included files
*******************************************************************************/
#include "demo_hal_dsi_tx.h"
#if AMOLED_NT37280
#include "hal_swire.h"
#endif

/*******************************************************************************
* 2.Global constant and macro definitions using #define
*******************************************************************************/
#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "tx-log"

#define DEMO_TX_VPG_EN               (0)    // 只适用于video模式输入video模式输出
#define DEMO_RX_GEN_PATTERN          (0)    // TX VPG和RX pattern不建议同时打开
#define DEMO_CCM_EN                  (0)    // 基于RX pattern数据通路进行CCM调整
#define DEMO_ENDIAN_EN               (0)    // RGB大小端配置
#define DEMO_OVERWRITE_EN            (0)    // Overwrite功能配置
#define DEMO_EDGE_DECT_EN            (0)    // 边缘检测功能配置
#define DEMO_EDGE_ENHANCE_EN         (0)    // 边缘增强功能配置
#define DEMO_FC_EN                   (0)    // false color功能配置
#define DEMO_BCS_EN                  (0)    // BCS调整功能配置
#define DEMO_BTA_LP_EN               (0)    // LP模式下BTA使用
#define DEMO_BTA_HS_EN               (0)    // HS传输过程中BTA使用


/* base_info输入端信息 */
#define INPUT_WIDTH                  (1440)
#define INPUT_HEIGHT                 (2960)
#define INPUT_SRC_FRATE              DSI_FRAME_RATE_60HZ
/* 输出数据格式(DSI_DATA_CMD_MODE , DSI_DATA_VIDEO_MODE) */
#define DSI_INPUT_DATA_MODE          DSI_DATA_VIDEO_MODE
#define DSI_OUTPUT_DATA_MODE         DSI_DATA_VIDEO_MODE
/* vid模式选择 */
#define OUTPUT_VID_SEL_MODE          DSI_BURST_MODE
/* 虚拟通道(0-3) */
#define VIRTUAL_CHANNEL              DSI_VC_0
/* TD_RSTN pin脚使用定义宏 */
#define PIN_TD_RSTN                  IO_PAD_TD_RSTN

#if DEMO_RX_GEN_PATTERN
/*输入mipi lane数量(DSI_RX_LANE_x x为1-4)*/
#define INPUT_MIPI_LANE_NUM          DSI_LANE_4
/*输入图像格式*/
#define INPUT_COLOR_MODE             DSI_RGB888
/*video mode输入时数据格式*/
#define INPUT_VIDEO_MODEL            DSI_NONBURST_EVENT
/*输入MIPI lane rate,video mode下需要计算delay,command mode可以不设置或者随便设置*/
#define INPUT_MIPI_LANE_RATE         (1200000000)
/*IPI pattern fps*/
#define PATTERN_FPS                  (60)
#endif

/*******************************************************************************
* 3.Global function and Global variable declarations
*******************************************************************************/
static hal_dsi_tx_ctrl_handle_t *g_tx_ctrl_handle = NULL;
#if DEMO_RX_GEN_PATTERN
static hal_dsi_rx_ctrl_handle_t *g_rx_ctrl_handle = NULL;
static uint8_t g_rx_pattern_sel = 0;   // 0:Vertical mode ; 1:Horizontal mode
#endif
static bool panel_init = false;

#if DEMO_BTA_LP_EN
static uint8_t bta_ack_data = 0;
#endif

#if DEMO_BTA_HS_EN
static bool sg_bta_need_flag = true;
#endif
/*******************************************************************************
* 4.Global function prototypes
*******************************************************************************/
#if AMOLED_NT37280
/**
* @brief  timer回调函数用于swire输出
* @param  data: 回调参数
* @retval 无
*/
static void demo_tx_timer_callback(void *data)
{
    hal_swire_set_waveform(12, 12, 12, 12);
    hal_swire_set_pulse(32);
}

/**
* @brief  打开屏背光
* @param  无
* @retval 无
*/
static void demo_tx_panel_backlight_on(void)
{
    hal_gpio_init_output(IO_PAD_AP_PWMEN, IO_LVL_HIGH);
    hal_swire_init();
    hal_swire_enable(true);

    hal_swire_set_waveform(12, 12, 12, 12);
    hal_swire_set_pulse(36);

    hal_timer_init(TIMER_NUM1);
    hal_timer_start(TIMER_NUM1, 16, demo_tx_timer_callback, NULL);

}
#endif

/**
* @brief PANEL初始化
* @param None
* @retval None
**/
void demo_panel_init(void)
{
#if AMOLED_NT37280
    demo_tx_panel_backlight_on();
#endif

    /*初始化TD_RSTN并产生屏端复位信号*/
    hal_gpio_init_output(PIN_TD_RSTN, IO_LVL_HIGH);
    hal_gpio_set_output_data(PIN_TD_RSTN, IO_LVL_HIGH);
    delayMs(10);
    hal_gpio_set_output_data(PIN_TD_RSTN, IO_LVL_LOW);
    delayMs(10);
    hal_gpio_set_output_data(PIN_TD_RSTN, IO_LVL_HIGH);
    delayMs(10);

    /*bta read register*/
#if DEMO_BTA_LP_EN
    hal_dsi_tx_ctrl_read_cmd(0x06, 0, 0xDA, 1, &bta_ack_data);
    TAU_LOGD("DA[0x%x]\n", bta_ack_data);
#endif

    /*initial code*/
#if LCD_PT628_CSOT
    TAU_LOGD("LCD_PT628_CSOT pannel init\n");
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0xBF, 0x00);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0xC0, 0x00);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0x00, 0x00);
    hal_dsi_tx_ctrl_write_cmd(0x39, 0, 4, 0xFF, 0x87, 0x56, 0x01);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0x00, 0x80);
    hal_dsi_tx_ctrl_write_cmd(0x39, 0, 3, 0xFF, 0x87, 0x56);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0x00, 0xE8);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0xC0, 0x20);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0x00, 0x00);
    hal_dsi_tx_ctrl_write_cmd(0x39, 0, 4, 0xFF, 0x87, 0x56, 0x01);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0x00, 0x80);
    hal_dsi_tx_ctrl_write_cmd(0x39, 0, 3, 0xFF, 0x87, 0x56);
    hal_dsi_tx_ctrl_write_cmd(0x05, 0, 1, 0x11);
    delayMs(120);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0x35, 0x00);
    hal_dsi_tx_ctrl_write_cmd(0x39, 0, 3, 0x51, 0x0F, 0xFF);
    hal_dsi_tx_ctrl_write_cmd(0x05, 0, 1, 0x29);

#elif AMOLED_NT37280
    TAU_LOGD("AMOLED_NT37280 pannel init\n");
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0xFF, 0xE0);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0xFB, 0x01);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0x18, 0x80);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0x1A, 0x15);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0x73, 0x01);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0x89, 0x7F);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0x0D, 0x9B);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0x46, 0x17);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0xFF, 0xF0);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0xFB, 0x01);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0x54, 0x03);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0x9C, 0x00);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0xFF, 0x20);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0xFB, 0x01);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0x34, 0x00);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0x35, 0x66);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0x36, 0x66);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0xFF, 0x10);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0xFB, 0x01);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0x88, 0x07);
    hal_dsi_tx_ctrl_write_cmd(0x39, 0, 5, 0x2A, 0x00, 0x00, 0x04, 0x37);
    hal_dsi_tx_ctrl_write_cmd(0x39, 0, 5, 0x2B, 0x00, 0x00, 0x08, 0xE7);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0x7F, 0x07);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0xE9, 0x00);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0xBF, 0x00);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0xC0, 0x00);
    hal_dsi_tx_ctrl_write_cmd(0x15, 0, 2, 0x35, 0x00);   //TE  35=00是标准60Hz; 35=01是有很多小信号
    hal_dsi_tx_ctrl_write_cmd(0x29, 0, 3, 0x51, 0x0F, 0xFF); //CABC
    hal_dsi_tx_ctrl_write_cmd(0x05, 0, 1, 0x11);
    delayMs(120);
    hal_dsi_tx_ctrl_write_cmd(0x05, 0, 1, 0x29);
    delayMs(10);
#endif

}

/**
* @brief RX初始化和开启
* @param None
* @retval None
**/
static void demo_open_mipi_rx(void)
{
    /*RX demo详细请参考demo_hal_dsi_rx*/
#if DEMO_RX_GEN_PATTERN
    /* 创建rx ctrl handle */
    if (g_rx_ctrl_handle == NULL)
    {
        g_rx_ctrl_handle = hal_dsi_rx_ctrl_create_handle();
    }
    g_rx_ctrl_handle->base_info.src_w = INPUT_WIDTH;
    g_rx_ctrl_handle->base_info.src_h = INPUT_HEIGHT;
    g_rx_ctrl_handle->base_info.dst_w = __DPI_HACT;
    g_rx_ctrl_handle->base_info.dst_h = __DPI_VACT;
    g_rx_ctrl_handle->rx_hsclk_rate = INPUT_MIPI_LANE_RATE;
    g_rx_ctrl_handle->base_info.src_frate = INPUT_SRC_FRATE;
    g_rx_ctrl_handle->base_info.src_mode = DSI_INPUT_DATA_MODE;
    g_rx_ctrl_handle->rx_color_mode = INPUT_COLOR_MODE;
    g_rx_ctrl_handle->rx_lanes = INPUT_MIPI_LANE_NUM;
    g_rx_ctrl_handle->rx_nonburst_models = INPUT_VIDEO_MODEL;

    /* 初始化rx ctrl */
    hal_dsi_rx_ctrl_init(g_rx_ctrl_handle);

    /* 配置RX video pattern */
    hal_dsi_rx_ctrl_enable_test_pattern(g_rx_ctrl_handle,  g_rx_pattern_sel, true, PATTERN_FPS);

    /* 启动rx ctrl */
    hal_dsi_rx_ctrl_start(g_rx_ctrl_handle);
#endif

}

/**
* @brief TX初始化和开启
* @param None
* @retval None
**/
static void demo_open_mipi_tx(void)
{
    /*创建TX实例*/
    if (g_tx_ctrl_handle == NULL)
    {
        g_tx_ctrl_handle = hal_dsi_tx_ctrl_create_handle();
    }
    g_tx_ctrl_handle->lane_num = _LANE_NUMBER;
    g_tx_ctrl_handle->channel_id = VIRTUAL_CHANNEL;
    g_tx_ctrl_handle->vid_mode = OUTPUT_VID_SEL_MODE;
    g_tx_ctrl_handle->cmd_tx_type = _CMD_TYPE;
    g_tx_ctrl_handle->dpi_vsa = __DPI_VSA;
    g_tx_ctrl_handle->dpi_vbp = __DPI_VBP;
    g_tx_ctrl_handle->dpi_vfp = __DPI_VFP;
    g_tx_ctrl_handle->dpi_hsa = __DPI_HSA;
    g_tx_ctrl_handle->dpi_hbp = __DPI_HBP;
    g_tx_ctrl_handle->dpi_hfp = __DPI_HFP;
    g_tx_ctrl_handle->base_info.src_w = INPUT_WIDTH;
    g_tx_ctrl_handle->base_info.src_h = INPUT_HEIGHT;
    g_tx_ctrl_handle->base_info.dst_w = __DPI_HACT;
    g_tx_ctrl_handle->base_info.dst_h = __DPI_VACT;
    g_tx_ctrl_handle->base_info.src_frate = INPUT_SRC_FRATE;
    g_tx_ctrl_handle->base_info.src_mode = DSI_INPUT_DATA_MODE;
    g_tx_ctrl_handle->base_info.dst_mode = DSI_OUTPUT_DATA_MODE;

#if LCD_PT628_CSOT  //RGBG玻璃匹配RGB Driver IC
    //remap规则参数， 此款玻璃remapl_rule/remapr_rule使用同一规则； 如果玻璃存在两个规则需要支持，请定义两个数组分别配置remapl_rule/remapr_rule
    remap_rule_t remap_rule =
    {
        9,  11,  12,  8,  7,  10,  4,  5,  6,  2, 1, 3,
        20, 19, 22, 21, 23, 24, 14, 13, 15, 16, 17, 18
    };
    g_tx_ctrl_handle->pentile_info.pentile_24b = true;           // 是否RGB驱动IC搭配RGBG玻璃使用
    g_tx_ctrl_handle->pentile_info.pentile_reverse_en = true;    // 是否需要使用芯片本身行反转功能
    g_tx_ctrl_handle->pentile_info.pentile_enable = true;        // 是否RGBG格式的数据传输
    g_tx_ctrl_handle->pentile_info.remapl_rule = &remap_rule;    // reamp规则1
    g_tx_ctrl_handle->pentile_info.remapr_rule = &remap_rule;    // reamp规则2
    g_tx_ctrl_handle->pentile_info.rgb_hact = 900;               // 如果是RGB驱动IC搭配RGBG玻璃使用，此处配置RGB驱动IC的分辨率；dst_w按玻璃分辨率进行配置
    /* RGBG 屏幕补黑配置，此款玻璃两块补黑区域均参与子像素重排*/
    g_tx_ctrl_handle->pentile_info.blank_info0.blank_en = 1;     // 是否使用补黑区域0
    g_tx_ctrl_handle->pentile_info.blank_info0.remap_en = 1;     // 补黑区域0是否参与remap重排
    g_tx_ctrl_handle->pentile_info.blank_info0.st_col = 0;       // 补黑区域0起始位置，按有效子像素序号进行计算
    g_tx_ctrl_handle->pentile_info.blank_info0.width = 12;       // 补黑区域0补黑宽度，按子像素级计算
    g_tx_ctrl_handle->pentile_info.blank_info1.blank_en = 1;     // 是否使用补黑区域1
    g_tx_ctrl_handle->pentile_info.blank_info1.remap_en = 1;     // 补黑区域1是否参与remap重排
    g_tx_ctrl_handle->pentile_info.blank_info1.st_col = 1248;    // 补黑区域1起始位置，按有效子像素序号进行计算，必须大于补黑区域0的起始位置
    g_tx_ctrl_handle->pentile_info.blank_info1.width = 216;      // 补黑区域1补黑宽度，按子像素级计算
#endif

#if DEMO_ENDIAN_EN
    hal_dsi_tx_ctrl_set_endianness(DPI_ENDIAN_BGR);// 默认RGB输出，可以更改为BGR 需要在初始化之前调用
#endif

    /*调用初始化接口进行TX初始化*/
    hal_dsi_tx_ctrl_init(g_tx_ctrl_handle);

    /*屏幕初始化，复位时序和发送initial code*/
    if (!panel_init)
    {
        demo_panel_init();
        panel_init = true;
    }

#if DEMO_TX_VPG_EN /*使用TX VPG测试TX是否正常工作*/
    hal_dsi_tx_ctrl_set_vpg(true, TX_VPG_V_COLOR, false);
#endif

    /*tx start开始传输高速数据*/
    hal_dsi_tx_ctrl_start(g_tx_ctrl_handle);

    /*可选功能配置，在任意时刻均可调用 start*/
#if DEMO_CCM_EN
    ccm_coef_t coef;
    coef.coef_c00 = 0x1f3;
    coef.coef_c01 = 0xf3a;
    coef.coef_c02 = 0xfd3;
    coef.coef_c10 = 0xf9c;
    coef.coef_c11 = 0x19c;
    coef.coef_c12 = 0xfca;
    coef.coef_c20 = 0x27;
    coef.coef_c21 = 0xf46;
    coef.coef_c22 = 0x193;
    hal_dsi_tx_ctrl_set_ccm(&coef);
#endif

#if DEMO_OVERWRITE_EN
    hal_dsi_tx_ctrl_set_overwrite_rgb(0x00, 0x00, 0xFF);      //蓝色图形数据输出 参数为R/G/B灰度值
    hal_dsi_tx_ctrl_overwrite_enable(true);                   //开启overwrite功能
    /*........*/
    //hal_dsi_tx_ctrl_overwrite_enable(false);                //需要关闭overwrite功能时调用
#endif

#if DEMO_EDGE_DECT_EN
    dsi_tx_edge_dect_t edge_dect_para = {0x10, true};
    hal_dsi_tx_ctrl_set_edge_dect(&edge_dect_para);
#endif

#if DEMO_EDGE_ENHANCE_EN
    dsi_tx_edge_enh_t edge_enh_para = {true, 64, 4, 64, 0};
    hal_dsi_tx_ctrl_set_edge_enhance(&edge_enh_para);
#endif

#if DEMO_FC_EN
    dsi_tx_fc_t fc_para = {64, 64};
    hal_dsi_tx_ctrl_set_fc(&fc_para);
#endif

#if DEMO_BCS_EN
    dsi_tx_bcs_t bcs_cfg = {0x00, 0x10, 0x10};               // 参数含义：{明亮度，对比度，饱和度}
    hal_dsi_tx_ctrl_set_bcs(&bcs_cfg);
#endif
    /*可选功能配置，在任意时刻均可调用 end*/

}

/**
* @brief  demo测试接口函数
* @param  None
* @retval None
*/
void demo_dsi_tx_case(void)
{
    TAU_LOGD("DSI TX DEMO.\n");
    demo_open_mipi_rx();
    demo_open_mipi_tx();

    while (1)
    {
#if DEMO_BTA_HS_EN
        if (sg_bta_need_flag) //当需要进行BTA回读的时候置标志位，等待Vporch阶段进行BTA回读获取有效数据
        {
            uint8_t bta_data = 0;
            if (hal_dsi_tx_ctrl_vporch_bta_opera(0x06, 0xDA, 1, &bta_data))
            {
                //Vporch阶段进行BTA回读获取到有效数据，关闭本次回读流程
                sg_bta_need_flag = false;
                TAU_LOGD("hs bta[0x%x]\n", bta_data);
            }
        }
#endif
    }

}

