/*******************************************************************************
*
*
* File:         hal_dsi_rx_ctrl.h
* Description:  hal mipi dsi rx path control 头文件
* Version:      V0.1
* Date:         2021-04-06
* Author:       lzy
 *******************************************************************************/
#ifndef __HAL_DSI_RX_CTRL_H__
#define __HAL_DSI_RX_CTRL_H__

/*******************************************************************************
* 1.Included files
*******************************************************************************/
#include "tau_dsi_datatype.h"
#include "tau_common.h"
#include "tau_log.h"

/*******************************************************************************
* 2.Global constant and macro definitions using #define
*******************************************************************************/
#define RX_DCS_QUEUE_MAX_SIZE 20  /* DCS存储队列长度 */

/*******************************************************************************
* 3.Global structures, unions and enumerations using typedef
*******************************************************************************/
typedef struct hal_dcs_execute_entry_t hal_dcs_execute_entry_t;

typedef struct hal_dcs_packet_t hal_dcs_packet_t;

typedef struct hal_dsi_rx_ctrl_handle_t hal_dsi_rx_ctrl_handle_t;

/* DCS CMD 回调函数, 注册进cus_dcs_entry_table里, 匹配对应的DCS 后回调*/
typedef bool (*hal_dsi_rx_ctrl_dcs_execute)(hal_dsi_rx_ctrl_handle_t *rx_handle, hal_dcs_packet_t *dcs_packet);

/* AP 读cmd 回调, 需要快速回CMD 时可注册, 为NULL 时DSC 读指令与写指令经过parse后由cus_dcs_entry_table回调 */
typedef bool (*hal_dsi_rx_ctrl_read_entry)(uint8_t data_type, uint8_t dcs_cmd, uint8_t param);

/* AP PPS 更新回调,参数为PPS 以及从PPS 里解析出来的picture width/height, 用于分辨率切换, 不注册该接口时内部处理PPS */
typedef bool (*hal_dsi_rx_ctrl_pps_entry)(uint8_t *pps, uint8_t size, uint32_t pic_width, uint32_t pic_height);

/**
* @brief hal_rx_event_e select
*/
typedef enum hal_rx_event_e
{
    HAL_RX_FS_EVENT     = 0x1,    /* Frame start event         */
    HAL_RX_LINE_EVENT   = 0x2,    /* Frame receive line event  */
    HAL_RX_END_EVENT    = 0x4,    /* Frame end event           */
} hal_rx_event_e;

/**
* @brief rx pq filter index
* 默认使用linear,特殊场景使用OPT filter
* RX_FLT_OPT_0最模糊,边缘最平滑,index越大越清晰,边缘锯齿会加重
*/
typedef enum
{
    RX_FLT_OPT_0    = 0,
    RX_FLT_OPT_1    = 1,
    RX_FLT_OPT_2    = 2,
    RX_FLT_OPT_3    = 3,
    RX_FLT_OPT_4    = 4,
    RX_FLT_OPT_5    = 5,
    RX_FLT_OPT_6    = 6,
    RX_FLT_OPT_7    = 7,
    RX_FLT_OPT_8    = 8,
    RX_FLT_OPT_9    = 9,
    RX_FLT_OPT_10   = 10,
    RX_FLT_LINEAR   = 11,
    RX_FLT_MAX
} hal_dsi_rx_pq_filter_e;

/* RX debug 回调函数,用于获取frame start 等功能debug */
typedef void (*hal_dsi_rx_ctrl_event_entry)(hal_rx_event_e event, void *data);

/**
* @brief  dsi rx ctrl handle struct
*/
typedef struct hal_dsi_rx_ctrl_handle_t
{
    dsi_base_trans_info_t            base_info;                 /* mipi video 转换基本信息 */
    dsi_base_extra_info_t            extra_info;                /* 新增旋转、镜像配置 */
    dsi_color_code_e                 rx_color_mode;             /* 输入color mode */
    dsi_lane_nume_e                  rx_lanes;                  /* mipi data lane */
    dsi_video_mode_type_e            rx_nonburst_models;        /* transmission packet sequences */
    bool                             compress_en;               /* DSC 压缩标志 */
    uint32_t                         rx_hsclk_rate;             /* mipi 高速信号lane rate */
    uint8_t                          rx_dsc_pps[DSC_PPS_SIZE];  /* DSC 压缩PPS参数 */
    const hal_dcs_execute_entry_t    *cus_dcs_entry_table;      /* DCS处理函数列表 */
    hal_dsi_rx_ctrl_read_entry       rx_dcs_read_entry;         /* Host读指令数据函数,为NULL时由rx_dcs_queue注册cmd处理 */
    hal_dsi_rx_ctrl_pps_entry        pps_update_entry;          /* PPS Update 时回调函数,用于分辨率切换更新PPS,为NULL时内部处理 */
    bool                             used;                      /* handle使用标志位 */
    hal_err_handle_level_e           err_handler_level;         /* RX接收错误的时候对模块做reset等级, 等级越高reset模块越多 */
    uint8_t                          rx_strength;               /* 用于调节RX信号强度，仅适用于开启内阻校准模式，档位0~7，默认3 */
    hight_performan_mode_e           hight_performan_mode;      /* 高性能模式等级,参考hight_performan_mode_e */
    dsi_rx_lane_swap_e               rx_lane_swap;              /* lane swap default order is 2103*/
    hal_dsi_rx_pq_filter_e           rx_pq_index;               /* 画质调整滤波器,默认为linear最优效果,特殊场景使用OPT filter */
} hal_dsi_rx_ctrl_handle_t;

/**
* @brief  DCS command execute entry
*/
typedef struct hal_dcs_execute_entry_t
{
    uint32_t dcs_command;                      /* DCS command */
    hal_dsi_rx_ctrl_dcs_execute execute_func;  /* command 对应处理函数 */
    bool immediately_func;                     /* 执行机制:true-在中断里立即执行,false-加入DCS队列异步执行 */
} hal_dcs_execute_entry_t;

/**
* @brief  存储 DCS packet 结构体
*/
typedef struct hal_dcs_packet_t
{
    uint32_t data_type;                        /* data type */
    uint32_t dcs_command;                      /* dcs command */
    uint32_t param_length;                     /* dcs param length */
    uint8_t *packet_param;                     /* dcs param */
    uint16_t crc_data;                         /* dcs crc */
    const hal_dcs_execute_entry_t *dcs_execute_entry;  /* dcs packet 处理函数入口*/
} hal_dcs_packet_t;

/**
* @brief video mode 下 RX pattern参数结构体
*/
typedef struct
{
    uint32_t                  ipi_pg_hsa;
    uint32_t                  ipi_pg_hbp;
    uint32_t                  ipi_pg_hfp;
    uint32_t                  ipi_pg_vsa;
    uint32_t                  ipi_pg_vbp;
    uint32_t                  ipi_pg_vfp;
    uint32_t                  frame_rate;
} hal_dsi_rx_ipi_pg_t;


/**
* @brief dcs command filter select
*/
typedef enum
{
    HAL_RX_DCS_FILTER_0 = 0x0,
    HAL_RX_DCS_FILTER_1 = 0x1,
    HAL_RX_DCS_FILTER_2 = 0x2,
    HAL_RX_DCS_FILTER_3 = 0x3,
    HAL_RX_DCS_FILTER_4 = 0x4,
    HAL_RX_DCS_FILTER_5 = 0x5,
    HAL_RX_DCS_FILTER_6 = 0x6,
    HAL_RX_DCS_FILTER_7 = 0x7,
    HAL_RX_DCS_FILTER_8 = 0x8,
    HAL_RX_DCS_FILTER_9 = 0x9,
    HAL_RX_DCS_FILTER_A = 0xA,
    HAL_RX_DCS_FILTER_B = 0xB,
    HAL_RX_DCS_FILTER_MAX
} hal_rx_dcs_filter_sel_e;


/**
* @brief dcs command filter select
*/
typedef enum
{
    HAL_RX_QRESP_CODE0 = 0,
    HAL_RX_QRESP_CODE1 = 1,
    HAL_RX_QRESP_CODE2 = 2,
    HAL_RX_QRESP_CODE3 = 3,
    HAL_RX_QRESP_CODE4 = 4,
    HAL_RX_QRESP_CODE5 = 5,
    HAL_RX_QRESP_CODE6 = 6,
    HAL_RX_QRESP_CODE7 = 7,
    HAL_RX_QRESP_MAX
} hal_rx_dcs_qresp_e;

/**
* @brief  pentile source color format
*/
typedef enum
{
    PENTILE_SRC_FORMAT_RGB           = 0x0,
    PENTILE_SRC_FORMAT_BGR           = 0x1,
    PENTILE_SRC_FORMAT_RGBG_BGRG     = 0x8,
    PENTILE_SRC_FORMAT_GBGR_GRGB     = 0x9,
    PENTILE_SRC_FORMAT_BGRG_RGBG     = 0xA,
    PENTILE_SRC_FORMAT_GRGB_GBGR     = 0xB,
    PENTILE_SRC_FORMAT_RGBG_RGBG     = 0xC,
    PENTILE_SRC_FORMAT_GBGR_GBGR     = 0xD,
    PENTILE_SRC_FORMAT_BGRG_BGRG     = 0xE,
    PENTILE_SRC_FORMAT_GRGB_GRGB     = 0xF,
    PENTILE_SRC_FORMAT_MAX
} pentile_src_format_e;

/**
* @brief 设置RX CLK
*/
typedef enum
{
    RX_CLK_100M   = 0,
    RX_CLK_150M   = 1,
    RX_CLK_200M   = 2,
    RX_CLK_300M   = 3,
    RX_CLK_40M   = 4,
    RX_CLK_80M   = 5,
    RX_CLK_MAX
} hal_rx_clk_e;

/**
* @brief pq_type_e select
*/
typedef enum
{
    PQ_TYPE_DEFAULT     = 0x0,
    PQ_TYPE_LIMIT       = 0x1,
    PQ_TYPE_MAX
} pq_type_e;

/**
* @brief 线的粗细
*/
typedef enum
{
    LINE_WEIGHT_FINE = 0,
    LINE_WEIGHT_MEDIUM = 1,
    LINE_WEIGHT_BOLD = 2,
    LINE_WEIGHT_MAX
} line_weight_e;

/*******************************************************************************
* 4.Global variable extern declarations
*******************************************************************************/

/*******************************************************************************
* 5.Global function prototypes
*******************************************************************************/

/**
* @brief  创建dsi rx ctrl handle (释放时需调用hal_dsi_rx_ctrl_release_handle)
* @param  none
* @retval dsi rx handle
*/
hal_dsi_rx_ctrl_handle_t *hal_dsi_rx_ctrl_create_handle(void);

/**
* @brief  释放dsi rx ctrl handle
* @param  rx_ctrl_handle: dsi rx handle
* @retval true/false
*/
bool hal_dsi_rx_ctrl_release_handle(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle);

/**
* @brief  设置rx ctrl handle 里的 PPS 参数
* @param  rx_ctrl_handle: dsi rx handle
* @param  pps: pps 参数
* @param  pps_size: pps 参数长度
* @retval true/false
*/
bool hal_dsi_rx_ctrl_pre_init_pps(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle, uint8_t pps[], uint32_t pps_size);

/**
* @brief  初始化dsi rx 模块
* @param  rx_ctrl_handle: dsi rx handle
* @retval true/false
*/
bool hal_dsi_rx_ctrl_init(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle);

/**
* @brief  dsi rx 模块去初始化
* @param  rx_ctrl_handle: dsi rx handle
* @retval true/false
*/
bool hal_dsi_rx_ctrl_deinit(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle);

/**
* @brief  启动dsi rx
* @param  rx_ctrl_handle: dsi rx handle
* @retval true/false
*/
bool hal_dsi_rx_ctrl_start(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle);

/**
* @brief  重新配置dsi rx参数并恢复状态 (debug使用, 重新配置rx_ctrl_handle参数后调用该接口重启)
* @param  rx_ctrl_handle: dsi rx handle
* @retval true/false
*/
bool hal_dsi_rx_ctrl_restart(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle);

/**
* @brief  停止dsi rx
* @param  rx_ctrl_handle: dsi rx handle
* @retval true/false
*/
bool hal_dsi_rx_ctrl_stop(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle);

/**
* @brief  手动设置RX clk,一般RX CLK 由底层自动计算,用于特殊video mode场景出现FIFO FULL情况调试使用
* @param  rxbr_clk: rx clk, 需要大于hs_lane_rate/8
* @retval true/false
*/
bool hal_dsi_rx_ctrl_set_rx_clk(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle, hal_rx_clk_e rxbr_clk);

/**
* @brief  发送 MIPI HOST的读响应 CMD
* @param  rx_ctrl_handle: dsi rx handle
* @param  data_type: data type
* @param  vc:        virtual channel
* @param  cmd_count: ack command 的长度
* @param  ...      : 需要发送的command(数量与cmd_count 配置一致)
* @retval true/false
*/
bool hal_dsi_rx_ctrl_send_ack_cmd(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle, dsi_ack_data_type_e data_type, dsi_virtual_channel_e vc, uint8_t cmd_count, ...);

/**
* @brief  使用数组方式回复短包,与hal_dsi_rx_ctrl_send_ack_cmd功能一致
* @param  rx_ctrl_handle: dsi rx handle
* @param  data_size: 数组长度,固定为4
* @param  data: 回复cmd数据,数据排列有严格规定:
* data[0]:DI(data type)
* data[1]:data 0
* data[2]:data 1
* data[3]:内部pkt type,短包固定为0
* @retval true/false
*/
bool hal_dsi_rx_ctrl_ack_short_cmd(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle, uint8_t data_size, uint8_t data[]);

/**
* @brief  使用数组方式回复长包,与hal_dsi_rx_ctrl_send_ack_cmd功能一致
* @param  rx_ctrl_handle: dsi rx handle
* @param  data_size: 数组长度,为Word Count + header长度 (header固定为4)
* @param  data: 回复cmd数据,数据排列有严格规定:
* data[0]:DI(data type)
* data[1]:wc 0 (Word Count 低八位)
* data[2]:wc 1 (Word Count 高八位)
* data[3]:内部pkt type,长包固定为1
* data[N]:长包数据
* @retval true/false
*/
bool hal_dsi_rx_ctrl_ack_long_cmd(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle, uint32_t data_size, uint8_t data[]);

/**
* @brief  异步处理DSC接口,执行cus_dcs_entry_table里对应DCS immediately_func为false的函数
* @param  rx_ctrl_handle: dsi rx handle
* @retval true - 正常处理1个DSC , false - 无DSC 处理
*/
bool hal_dsi_rx_ctrl_dcs_async_handler(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle);

/**
* @brief  使用硬件filter丢弃不需要处理的CMD,避免MCU资源被无效CMD占用
* @param  rx_ctrl_handle: dsi rx handle
* @param  filter_number: filter 编号(0-7)
* @param  cmd_start: 需要丢弃command code起始位
* @param  cmd_end: 需要丢弃command code终止位
* @retval true/false
*/
bool hal_dsi_rx_ctrl_set_hw_cmd_filter(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle,
                                       hal_rx_dcs_filter_sel_e filter_number,
                                       uint32_t cmd_start, uint32_t cmd_end);

/**
* @brief  使用内置pattern代替mipi输入(用于测试)
* @param  rx_ctrl_handle: dsi rx handle
* @param  pg_orient: pattern 方向(0:Vertical mode ; 1:Horizontal mode)
* @param  enable: 开启/关闭pattern
* @param  frame_rate: pattern 帧率
* @retval true/false
*/
bool hal_dsi_rx_ctrl_enable_test_pattern(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle, uint8_t pg_orient, bool enable, int frame_rate);


/**
* @brief  获取AP 配置 BTA回复数据最大size
* @param  rx_ctrl_handle: dsi rx handle
* @retval 返回数据大小
*/
uint32_t hal_dsi_rx_ctrl_get_max_ret_size(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle);

/**
* @brief  获取AP Compression Mode Command配置,默认为0,谨慎使用
* @param  rx_ctrl_handle: dsi rx handle
* @retval AP 配置compressen_en
*/
bool hal_dsi_rx_ctrl_get_compressen_en(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle);

/**
* @brief  输入分辨率切换接口
* @param  rx_ctrl_handle: dsi rx handle
* @retval true/false
*/
bool hal_dsi_rx_ctrl_toggle_resolution(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle);

/**
* @brief  配置 RX escape clk
* @param  rx_ctrl_handle: dsi rx handle
* @param  esc_clk: escape clk 单位Hz,10000000时回CMD为10Mhz
* @retval true/false
*/
bool hal_dsi_rx_ctrl_set_cus_esc_clk(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle, uint32_t esc_clk);

/**
* @brief  自动计算并配置硬件filter
* @param  rx_ctrl_handle: dsi rx handle
* @param  enable: 启动/关闭 硬件filter
* @retval true/false
*/
bool hal_dsi_rx_ctrl_set_auto_hw_filter(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle, bool enable);

/*
* @brief  输入帧率修改(针对video mode)
* @param  rx_ctrl_handle: dsi rx handle
* @param  frame_rate：frame rate
*/
bool hal_dsi_rx_ctrl_toggle_input_frame_rate(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle, dsi_video_frame_rate_e frame_rate);

/*
* @brief  注册写命令的回调函数,用于特殊命令序列时写命令的处理.
          可配合hal_dsi_rx_ctrl_set_auto_hw_filter关闭hw filter用于获取所有软件CMD
* @param  rx_ctrl_handle: dsi rx handle
* @param  写命令处理函数
* @retval none
*/
void hal_dsi_rx_ctrl_register_write_cmd_entry(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle, hal_dsi_rx_ctrl_dcs_execute execute_func);

/**
* @brief  配置硬件自动回复命令
*         最大回复长度64,AP需要配置set_max_return_size后并且对比一直才会自动回复,不需要软件再参与
*         应用于所有回复固定数据的场景
* @param  RXBR: registers struct
* @param  qresp_number: qresp 编号(0-7)
* @param  data_type: 需要回复的读命令的datatype
* @param  cmd_code: 需要回复的读命令
* @param  cmd_count: 需要回复的命令的大小,长包最大size为64,与set_max_return_size一致才会回复
* @param  ...: 需要回复的参数
* @retval true/false
*/
bool hal_dsi_rx_ctrl_set_auto_ack(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle, hal_rx_dcs_qresp_e qresp_number,  dsi_ack_data_type_e data_type, uint32_t cmd_code, uint8_t cmd_count, ...);

/*
* @brief  初始化画点模式
* @param  rx_ctrl_handle: dsi rx handle
* @param  draw_en: 画点模式使能
* @param  pxl_init_en: 是否对全屏数据赋值,true:使用init_value赋值,false:使用上一帧数据作为初始值
* @param  color_mode: 画点模式数据源格式见dsi_color_code_e
* @param  init_value: 全屏初始化数据,bit[23:16]--R，bit[15:8]--G，bit[7:0]--B
* @retval none
*/
void hal_dsi_rx_ctrl_draw_mode_init(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle, bool draw_en, bool pxl_init_en, dsi_color_code_e color_mode, uint32_t init_value);

/*
* @brief  配置像素颜色
* @param  rx_ctrl_handle: dsi rx handle
* @param  x: 像素点的x 坐标
* @param  y: 像素点的y 坐标
* @param  red_data: 像素点R分量
* @param  green_data: 像素点G分量
* @param  blue_data: 像素点B分量
* @retval none
*/
void hal_dsi_rx_ctrl_set_pixel_data(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle, int x, int y, uint8_t red_data, uint8_t green_data, uint8_t blue_data);


/**
* @brief  video mode下强制将数据设置为特定的color mode,具体type见dsi_color_code_e
* @param  rx_ctrl_handle: dsi rx handle
* @param  enable: 使能强制数据模式
* @param  frc_vid_code: 强制的数据格式
* @retval none
*/
void hal_dsi_rx_ctrl_force_video_crtl(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle, bool enable, dsi_color_code_e frc_vid_code);

/**
* @brief  注册RX 事件回调函数
* @param  rx_ctrl_handle: dsi rx handle
* @param  event_cb: 回调函数
* @param  event_mask: 接收事件掩码,见hal_rx_event_e(eg:HAL_RX_FS_EVENT|HAL_RX_LINE_EVENT)
* @param  enable: 事件回调开关
* @param  user_data: 预留扩展参数,不同事件事件配置不同参数
* @retval none
*/
void hal_dsi_rx_ctrl_register_callback(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle, hal_dsi_rx_ctrl_event_entry event_cb, uint32_t event_mask, bool enable, void *user_data);

/**
* @brief  配置是否打开长包CRC检查
* @param  rx_ctrl_handle: dsi rx handle
* @param  enable: 开启或者屏蔽CRC检测
* @retval none
*/
void hal_dsi_rx_ctrl_set_check_crc(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle, bool enable);

/**
* @brief  配置rx log 等级
* @param  rx_drv_level: rx log等级见枚举log_level_e
* @retval none
*/
void hal_dsi_rx_ctrl_set_log_level(log_level_e rx_drv_level);

/**
 * @brief   带颜色画线函数(直线、斜线)
 * @param   x1,y1   起点坐标
 * @param   x2,y2   终点坐标
 * @param  red_data: 像素点R分量
 * @param  green_data: 像素点G分量
 * @param  blue_data: 像素点B分量
 * @param  line_weight: 线粗
 * @return  none
 */
void hal_dsi_rx_ctrl_draw_line(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2,  uint8_t red_data, uint8_t green_data, uint8_t blue_data, line_weight_e line_weight);

/**
 * @brief   设置需要获取pixel的坐标
 * @param  cap_x: 抓取pixel的x坐标
 * @param  cap_y: 抓取pixel的y坐标
 * @return  none
 */
void hal_dsi_rx_ctrl_set_cap_pixel_pos(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle, uint16_t x0, uint16_t y0);

/**
 * @brief   获取指定坐标颜色,必须先设置获取颜色的坐标
 * @return  返回指定坐标颜色
 */
uint32_t hal_dsi_rx_ctrl_get_cap_pixel_color(hal_dsi_rx_ctrl_handle_t *rx_ctrl_handle);

#endif //__HAL_DSI_RX_CTRL_H__
