天天看點

BES key講解

  下面來講解下BES的按鍵,按鍵的定義、時間、多擊靈敏度等都是在 hal_key.c 裡面去修改的。如下代碼:

1、添加多擊事件

...
#ifndef CFG_SW_KEY_INIT_LLPRESS_THRESH_MS
#define CFG_SW_KEY_INIT_LLPRESS_THRESH_MS   10000
#endif
// 多擊之間的間隔時間。如果不夠靈敏那就将這值調小
#ifndef CFG_SW_KEY_CHECK_INTERVAL_MS
#define CFG_SW_KEY_CHECK_INTERVAL_MS        40
#endif
//common key define
#define KEY_LONGLONGPRESS_THRESHOLD         MS_TO_TICKS(CFG_SW_KEY_LLPRESS_THRESH_MS)
#define KEY_LONGPRESS_THRESHOLD             MS_TO_TICKS(CFG_SW_KEY_LPRESS_THRESH_MS)
#define KEY_DOUBLECLICK_THRESHOLD           MS_TO_TICKS(CFG_SW_KEY_DBLCLICK_THRESH_MS)
#define KEY_LONGPRESS_REPEAT_THRESHOLD      MS_TO_TICKS(CFG_SW_KEY_REPEAT_THRESH_MS)

#define KEY_INIT_DOWN_THRESHOLD             MS_TO_TICKS(CFG_SW_KEY_INIT_DOWN_THRESH_MS)
#define KEY_INIT_LONGPRESS_THRESHOLD        MS_TO_TICKS(CFG_SW_KEY_INIT_LPRESS_THRESH_MS)
#define KEY_INIT_LONGLONGPRESS_THRESHOLD    MS_TO_TICKS(CFG_SW_KEY_INIT_LLPRESS_THRESH_MS)

#define KEY_CHECKER_INTERVAL                MS_TO_TICKS(CFG_SW_KEY_CHECK_INTERVAL_MS)

#define KEY_DEBOUNCE_INTERVAL               (KEY_CHECKER_INTERVAL * 2)
#define KEY_DITHER_INTERVAL                 (KEY_CHECKER_INTERVAL * 1)
// 設定多擊的個是。有多少擊就将 HAL_KEY_EVENT_NINECLICK 改掉。相應的也要在hal_key.h中添加相應的 多擊
#define MAX_KEY_CLICK_COUNT                 (HAL_KEY_EVENT_NINECLICK - HAL_KEY_EVENT_CLICK)
           

hal_key.h

enum HAL_KEY_EVENT_T {
    ...
    // 下面這些就是添加的相應多擊
    HAL_KEY_EVENT_CLICK,
    HAL_KEY_EVENT_DOUBLECLICK,
    HAL_KEY_EVENT_TRIPLECLICK,
    HAL_KEY_EVENT_ULTRACLICK,
    HAL_KEY_EVENT_RAMPAGECLICK,
    HAL_KEY_EVENT_SIXCLICK,
    HAL_KEY_EVENT_SEVENCLICK,
    HAL_KEY_EVENT_EIGHTCLICK,
    HAL_KEY_EVENT_NINECLICK,
    HAL_KEY_EVENT_REPEAT,
...
    HAL_KEY_EVENT_NUM,
};
           

app_key.h 中也要去添加相應的。友善應用層去調用。代碼如下:

enum APP_KEY_EVENT_T {
...
    APP_KEY_EVENT_LONGLONGPRESS      = HAL_KEY_EVENT_LONGLONGPRESS,
    APP_KEY_EVENT_CLICK              = HAL_KEY_EVENT_CLICK,  // 單擊
    APP_KEY_EVENT_DOUBLECLICK        = HAL_KEY_EVENT_DOUBLECLICK,  // 輕按兩下
    APP_KEY_EVENT_TRIPLECLICK        = HAL_KEY_EVENT_TRIPLECLICK,  // 三擊 10
    APP_KEY_EVENT_ULTRACLICK         = HAL_KEY_EVENT_ULTRACLICK,  // 四擊
    APP_KEY_EVENT_RAMPAGECLICK       = HAL_KEY_EVENT_RAMPAGECLICK,  // 五擊
    APP_KEY_EVENT_SIXCLICK           = HAL_KEY_EVENT_SIXCLICK,      // 六擊 13
    APP_KEY_EVENT_SEVENCLICK         = HAL_KEY_EVENT_SEVENCLICK,
    APP_KEY_EVENT_EIGHTCLICK         = HAL_KEY_EVENT_EIGHTCLICK,
    APP_KEY_EVENT_NINECLICK          = HAL_KEY_EVENT_NINECLICK,     
    APP_KEY_EVENT_REPEAT             = HAL_KEY_EVENT_REPEAT,
...
    APP_KEY_EVENT_NUM = HAL_KEY_EVENT_NUM,
};
           

2、添加長按事件

hal_key.c

#ifndef CFG_SW_KEY_LLLPRESS_THRESH_MS
#define CFG_SW_KEY_LLLPRESS_THRESH_MS       10000
#endif
// 添加自己定義的長按事件
#ifndef CFG_SW_KEY_LLPRESS_PH6_MS
#define CFG_SW_KEY_LLPRESS_PH6_MS           6000
#endif
#define KEY_LONGLONGLONGPRESS_THRESHOLD         MS_TO_TICKS(CFG_SW_KEY_LLLPRESS_THRESH_MS)
// 自定義
#define KEY_LONGLONGPH6PRESS_THRESHOLD         MS_TO_TICKS(CFG_SW_KEY_LLPRESS_PH6_MS)

static void hal_key_debounce_handler(void *param)
{
    ...
    // LongPress should be stopped if any key is released
    if ((code_down & key_status.code_ready) == key_status.code_ready) {
        if (key_status.event == HAL_KEY_EVENT_DOWN) {
            if (time - key_status.time_updown >= KEY_LONGPRESS_THRESHOLD) {
                key_status.cnt_repeat = 0;
                key_status.event = HAL_KEY_EVENT_LONGPRESS;
                send_key_event(key_status.code_ready, key_status.event);
            }
        } else if (key_status.event == HAL_KEY_EVENT_LONGPRESS || key_status.event == HAL_KEY_EVENT_LONGLONGPRESS ||
           key_status.event == HAL_KEY_EVENT_LONGLONGPH6PRESS ||\
           key_status.event == HAL_KEY_EVENT_LONGLONGPH7PRESS || key_status.event == HAL_KEY_EVENT_LONGLONGLONGPRESS) 
        {
            ...
            else if (key_status.event == HAL_KEY_EVENT_LONGLONGPRESS) {
                if (time - key_status.time_updown >= KEY_LONGLONGPH6PRESS_THRESHOLD) {
                    key_status.event = HAL_KEY_EVENT_LONGLONGPH6PRESS;
                    send_key_event(key_status.code_ready, key_status.event);
                }
            }
            else if (key_status.event == HAL_KEY_EVENT_LONGLONGPH6PRESS) {
                if (time - key_status.time_updown >= KEY_LONGLONGPH7PRESS_THRESHOLD) {
                    key_status.event = HAL_KEY_EVENT_LONGLONGPH7PRESS;
                    send_key_event(key_status.code_ready, key_status.event);
                }
            }
            else if (key_status.event == HAL_KEY_EVENT_LONGLONGPH7PRESS) {
                if (time - key_status.time_updown >= KEY_LONGLONGLONGPRESS_THRESHOLD) {
                    key_status.event = HAL_KEY_EVENT_LONGLONGLONGPRESS;
                    send_key_event(key_status.code_ready, key_status.event);
                    }
                }
        }
    }
    if (key_status.event != HAL_KEY_EVENT_NONE) {
        need_timer = true;
    }
    ...
}
           

以上的代碼是要對自己定義的長按在code中進行處理的。如果這裡不加,那麼就不會有自己定義的長按事件出現

hal_key.h

enum HAL_KEY_EVENT_T {
    ...
    HAL_KEY_EVENT_LONGLONGPRESS,  // 4s
    HAL_KEY_EVENT_LONGLONGPH6PRESS,  // 6s
    HAL_KEY_EVENT_LONGLONGPH7PRESS,
    HAL_KEY_EVENT_LONGLONGLONGPRESS,  // 10s
    ...
    HAL_KEY_EVENT_NUM,
};
           

app_key.h ( 以下定義的是友善應用層調用)

enum APP_KEY_EVENT_T {
    ...
    APP_KEY_EVENT_UP_AFTER_LONGPRESS = HAL_KEY_EVENT_UP_AFTER_LONGPRESS,  // 5
    APP_KEY_EVENT_LONGPRESS          = HAL_KEY_EVENT_LONGPRESS,
    APP_KEY_EVENT_LONGLONGPRESS      = HAL_KEY_EVENT_LONGLONGPRESS,
    APP_KEY_EVENT_LONGLONGPH6GPRESS  = HAL_KEY_EVENT_LONGLONGPH6PRESS,
    APP_KEY_EVENT_LONGLONGPH7GPRESS  = HAL_KEY_EVENT_LONGLONGPH7PRESS,
    APP_KEY_EVENT_LONGLONGLONGPRESS  = HAL_KEY_EVENT_LONGLONGLONGPRESS,
    ...
    APP_KEY_EVENT_NUM = HAL_KEY_EVENT_NUM,
};
           

3、app_key_init() 函數 對按鍵進行注冊。

4、進入DUT模式之後,是使用 app_factorymode_key_init() 函數進行注冊的。

是以有效的按鍵就看函數中注冊了多少功能函數。

5、開機的時候會根據按鍵按壓的時間來修改 g_pwron_case 的狀态。代碼如下:

const  APP_KEY_HANDLE  pwron_key_handle_cfg[] = {
    {{APP_KEY_CODE_PWR,APP_KEY_EVENT_INITUP},           "power on: normal"     , app_poweron_normal, NULL},
    {{APP_KEY_CODE_PWR,APP_KEY_EVENT_INITLONGPRESS},    "power on: both scan"  , app_poweron_scan  , NULL},
    {{APP_KEY_CODE_PWR,APP_KEY_EVENT_INITFINISHED},     "power on: finished"   , app_poweron_finished  , NULL},
};
           

6、預設的長按開機改為短按開機。代碼如下:

int hal_key_open(int checkPwrKey, int (* cb)(uint32_t, uint8_t))
{
...
// 将下面宏裡面的一段注釋掉就變成單擊開機
#ifdef CHECK_PWRKEY_AT_BOOT
    if (checkPwrKey) {
        int cnt;
        int i = 0;

        if (hal_get_chip_metal_id() < HAL_CHIP_METAL_ID_3) {
            cnt = 1;
        } else {
            cnt = 10;
        }
        cnt = 18;

        do {
            hal_sys_timer_delay(MS_TO_TICKS(20));
            if (!hal_pwrkey_startup_pressed()) {
                HAL_KEY_TRACE("pwr_key init DITHERING");
                nRet = -1;
                goto _exit;
            }
        } while (++i < cnt);
    }
#endif
...
}
           

7、撥動開關進行開關機。代碼如下:

hal_key.c

static inline void hal_pwrkey_enable_int(void)
{
    // 修改進入中斷函數為上升和下降
    hal_pwrkey_enable_bothedge_int();
}
// 下面的函數是耳機開機一直長按會在這個中斷函數中不會自己調出來。是以手動添加個跳出函數的判斷
bool pwr_key_up;
static void hal_pwrkey_handle_irq_state(enum HAL_PWRKEY_IRQ_T state)
{
    pwr_key_up = false;
 ...
        {
            pwr_key.pressed = hal_pwrkey_pressed();
            if (pwr_key.pressed) {
                pwr_key.debounce = true;
            } else {
                pwr_key.dither = true;
            }
        }
        pwr_key.time = time;
    }
    else {
        TRACE("==> pwr key irq up !!!");
        //app_shutdown();
        pwr_key_up = true;
        }
 ...
}

static void hal_key_debounce_handler(void *param)
{
    ...
    enum HAL_KEY_CODE_T down_new;
    enum HAL_KEY_CODE_T up_new;
    enum HAL_KEY_CODE_T map;
    down_new = code_down & ~key_status.code_down;
    up_new = ~code_down & key_status.code_down;
    // Check newly up keys
    if (pwr_key_up == true) {
        up_new = pwr_key_up;
    }
    map = up_new;
    index = 0;
    while (map) {
    ...
            key_status.time_updown = time;
        }
        index++;
    }
    if (pwr_key_up)
    {
        key_status.code_click = HAL_KEY_CODE_NONE;
        key_status.cnt_click = 0;
        key_status.event = HAL_KEY_EVENT_NONE;
        pwr_key_up = false;
    }
    if (up_new) {
        if (key_status.event == HAL_KEY_EVENT_LONGPRESS || key_status.event == HAL_KEY_EVENT_LONGLONGPRESS || \
            key_status.event == HAL_KEY_EVENT_LONGLONGPH5PRESS || key_status.event == HAL_KEY_EVENT_LONGLONGLONGPRESS) {
            // LongPress is finished when all of the LongPress keys are released
            if ((code_down & key_status.code_ready) == 0) {
                key_status.event = HAL_KEY_EVENT_NONE;
            }
     ...
}
static void hal_key_boot_handler(void *param)
{
    ...
        else if (key_status.event == HAL_KEY_EVENT_INITLONGPRESS) {
                if (time - key_status.time_updown >= KEY_INIT_LONGLONGPRESS_THRESHOLD) {
                    key_status.event = HAL_KEY_EVENT_INITLONGLONGPRESS;
                    send_key_event(HAL_KEY_CODE_PWR, key_status.event);
                }
            }
        }
        if ((time - key_status.time_updown) > MS_TO_TICKS(2000))
            goto exit;
        hal_key_debounce_timer_restart();
    } else {
        if (key_status.event == HAL_KEY_EVENT_NONE || key_status.event == HAL_KEY_EVENT_INITDOWN) {
            send_key_event(HAL_KEY_CODE_PWR, HAL_KEY_EVENT_INITUP);
        }
exit:
        send_key_event(HAL_KEY_CODE_PWR, HAL_KEY_EVENT_INITFINISHED);

        hwtimer_update(debounce_timer, hal_key_debounce_handler, NULL);
        hal_sys_wake_unlock(HAL_SYS_WAKE_LOCK_USER_KEY);

        memset(&key_status, 0, sizeof(key_status));
        hal_pwrkey_reset();
        hal_key_enable_allint();
    }      
}
           

apps.c

const  APP_KEY_HANDLE  pwron_key_handle_cfg[] = {
    {{APP_KEY_CODE_PWR,APP_KEY_EVENT_INITUP},           "power on: normal"     , app_poweron_normal, NULL},
};
           

8、同時長按觸發。代碼如下:(PS:還需要優化,思路是這樣的)

apps.c

// 功能函數 同時長按進DUT
void app_bt_groupkey(APP_KEY_STATUS *status, void* param)
{
    uint16_t i = 0;
    uint8_t j = 0;
    //bool groupkey_detected = false;
    //APP_KEY_HANDLE key_none_handle_cfg = {{APP_KEY_CODE_NONE,APP_KEY_EVENT_NONE},"none function key",app_bt_nonekey,NULL};
    TRACE("==> %s event|code = %d|%d", __func__, status->event, status->code);
    if (status->event != APP_KEY_EVENT_DOWN || connect_mobile_flag/*|| app_status_indication_get() == APP_STATUS_INDICATION_BOTHSCAN*/)
    	return;
	
    switch (status->code) {
    	case APP_KEY_CODE_PWR:
    		do {
                TRACE("===> i = %d", i);
    			if (app_bt_key_read(APP_KEY_CODE_FN3) == APP_KEY_EVENT_DOWN) {
                    TRACE("#### input DUT ########");
                    j++;
                    if (j == 200) {
                    app_factorymode_enter();
    				break;
                    }
    			}
                if (i > 40 && j == 0)
                    break;
    			osDelay(30);
    		} while(i++<250);
    		break;
        default:
            TRACE("==> %s unregister down key event", __func__);
            break;
    }
}
// 在按鍵初始化的時候,注冊的功能按鍵
const APP_KEY_HANDLE  app_key_handle_cfg[] = {
    {{APP_KEY_CODE_PWR,APP_KEY_EVENT_DOWN},"bt function key",app_bt_groupkey, NULL},
    {{HAL_KEY_CODE_FN3,APP_KEY_EVENT_DOWN},"bt function key",app_bt_groupkey, NULL},
}
           

key相關的已經講解完了。