/**
 *@file sr_key.h
 *@brief KEY抽象接口
 *@details 提供KEY检测相关枚举、结构体
 *@copyright Copyright (c) 2024 lierda. All rights reserved.
 *@author Lierda-RDC
 *@date 2024-04-01
 *@example ZhaoyangSDK\example\component\key_example.c
 */

#ifndef _SR_KEY_H
#define _SR_KEY_H

#include "sr_config.h"
#include "board.h"
#include "sr_stddef.h"

#ifndef SR_KEY_SCAN_PERIOD    /*!<按键扫描周期 ，单位 ms */
#define SR_KEY_SCAN_PERIOD    10 // 默认10ms

#endif

#if (SR_KEY_SCAN_PERIOD == 10) // 10ms扫描周期，支持单击/双击/长按松开检测、自定义状态检测
#define _TIME_UNIT 10

#ifndef SR_KEY_DELAY_SHORT
#define SR_KEY_DELAY_SHORT 1   /*!<单击松开检测延时 单位10ms */
#endif

#ifndef SR_KEY_DELAY_LONG
#define SR_KEY_DELAY_LONG  200 /*!<长按松开最小检测延时 单位10ms */
#endif

#elif (SR_KEY_SCAN_PERIOD == 1000) // 1s扫描周期(只支持长按并松开、自定义状态检测)
#define _TIME_UNIT 1

#ifndef SR_KEY_DELAY_LONG
#define SR_KEY_DELAY_LONG 2 /*!<长按最小检测延时 单位s */
#endif

#endif

#define SR_LVL_PRESSED     1  /*!<按下电平  */
#define SR_LVL_RELEASE     0  /*!<松开电平  */



/**
 * @brief 按键索引,ID号
 */
#ifndef SR_KEY_NUM
#define SR_KEY_NUM 1
#endif
typedef enum SR_KEY_ID
{
#if (SR_KEY_NUM >= 1)
    KEY0 = 0u,
#endif
#if (SR_KEY_NUM >= 2)
    KEY1,
#endif
#if (SR_KEY_NUM >= 3)
    KEY2,
#endif
#if (SR_KEY_NUM >= 4)
    KEY3,
#endif
    KEY_MAX
} SR_KEY_ID_E;

/**
 * @brief 组件自带的的按键事件枚举
 */
typedef enum SR_KEY_EVT
{
    SR_KEY_SHORT_PRESS = 0x00660000, /*!<单击（短按）*/
    SR_KEY_DOUBLE_PRESS ,            /*!<双击*/
    SR_KEY_LONG_PRESS ,              /*!<长按xx时间后松开*/
    

} SR_KEY_EVT_E;

/**
 * @brief 设置按键状态事件通知回调
 *
 * @param[in] id     按键ID号
 * @param[in] state  按键状态
 * @param[in] time   时长. 10ms扫描周期：单位是ms; 1s扫描周期: 单位是s .(长按后松开、自定义检测时有效)
 * @param[in] args   用户参数
 *
 * @return 成功返回0，失败返回错误码
 */
typedef void (*KeyEventCb)(SR_KEY_ID_E id, SR_KEY_EVT_E evt, uint16_t time, void *args);

/**
 * @brief KEY按键按下事件结构体，检测时间点
 */
typedef struct
{
	uint16_t evtId;        /*!< 自定义事件ID*/
    uint16_t time;         /*!< 按键按下后，触发时间点。10ms扫描周期：单位是ms; 1s扫描周期: 单位是s*/

} SR_KEY_PRES_T;

/**
 * @brief KEY按键释放事件结构体（检测时间段）
 */
typedef struct
{
    uint16_t evtId;        /*!< 自定义事件ID*/
    uint16_t startTime;    /*!< 按键抬起后，触发时间段的起始,含。10ms扫描周期：单位是ms; 1s扫描周期: 单位是s*/
    uint16_t endTime;      /*!< 按键抬起后，触发时间段的结束, 不包含。10ms扫描周期：单位是ms; 1s扫描周期: 单位是s*/

} SR_KEY_RLS_T;

/**
 * @brief KEY管理器结构体
 */
typedef struct
{
    uint16_t delay;           /*!< 延时计数*/
    uint16_t multi_delay;     /*!< 连按延时计数*/
    uint8_t  multi_press : 3; /*!< 按下次数计数*/
    uint8_t  state : 1;       /*!< 按键当前状态    0：松开       1：按下*/

    SR_KEY_PRES_T *pressEvt;  /*!< 自定义按下事件*/
    uint8_t pressEvtNum;      /*!< 自定义事件的数量*/

    SR_KEY_RLS_T *rlsEvt;     /*!< 自定义释放事件*/
    uint8_t rlsEvtNum;        /*!< 自定义释放事件的数量*/

} SR_KEY_MNG_T;

/**
 * @brief 按键事件回调结构体
 */
typedef struct
{
    KeyEventCb cb;
    void *args;
} SR_KEY_CB_T;

/*-----------------------------------内部接口-----------------------*/

/**
 * @brief 按键状态检测任务，10ms/1s周期执行
 *
 * @return 无
 */
void SR_KeyScanTask(void);

/*-----------------------------------对外抽象接口--------------------*/

/**
 * @brief 设置按键状态事件通知回调
 *
 * @param[in] cb    用户回调函数
 * @param[in] args  用户参数
 *
 * @return 成功返回0，失败返回错误码
 */
int SR_KeySetEvtCb(KeyEventCb cb, void *args);

/**
 * @brief 注册按键按下的触发时长以及事件
 *
 * @param[in] keyId        按键ID
 * @param[in] pressEvt     按键按下事件结构体
 * @param[in] evtNum       按键按下事件的个数
 *
 * @return 成功返回0，失败返回错误码
 */
int SR_KeyPressEvtReg(SR_KEY_ID_E keyId, SR_KEY_PRES_T *pressEvt, uint8_t evtNum);

/**
 * @brief 注册按键释放的触发时长以及事件
 *
 * @param[in] keyId       按键ID
 * @param[in] rlsEvt      按键释放事件结构体
 * @param[in] rlsEvtNum   按键释放事件的个数
 *
 * @return 成功返回0，失败返回错误码
 */
int SR_KeyRlsEvtReg(SR_KEY_ID_E keyId, SR_KEY_RLS_T *rlsEvt, uint8_t evtNum);



/**
 * @brief 返回按键的当前状态
 *
 * @param[in] keyId       按键ID
 *
 * @return 0：松开   1：按下
 */
uint8_t SR_KeyGetState(SR_KEY_ID_E keyId);


/**
 * @brief 返回按键的当前实时按下时间计数
 *
 * @param[in] keyId       按键ID
 *
 * @return >=0：时间计数（10ms扫描周期：单位是ms; 1s扫描周期: 单位是s）   
 */
uint16_t SR_KeyGetCnt(SR_KEY_ID_E keyId);


/*-----------------------------------------------------------------*/

#endif
