#include "bsp_key.h" #include "flexible_button.h" #include "bsp_uart.h" #include "log.h" #include "SLEEP.h" // https://www.cnblogs.com/iot-fan/p/14304943.html #undef LOG_ENABLE #define LOG_ENABLE 1 #undef LOG_TAG #define LOG_TAG "key" typedef enum { USER_BUTTON_0 = 0, USER_BUTTON_MAX } user_button_t; #if 1 #define ENUM_TO_STR(e) (#e) static char *enum_event_string[] = { ENUM_TO_STR(FLEX_BTN_PRESS_DOWN), ENUM_TO_STR(FLEX_BTN_PRESS_CLICK), ENUM_TO_STR(FLEX_BTN_PRESS_DOUBLE_CLICK), ENUM_TO_STR(FLEX_BTN_PRESS_REPEAT_CLICK), ENUM_TO_STR(FLEX_BTN_PRESS_SHORT_START), ENUM_TO_STR(FLEX_BTN_PRESS_SHORT_UP), ENUM_TO_STR(FLEX_BTN_PRESS_LONG_START), ENUM_TO_STR(FLEX_BTN_PRESS_LONG_UP), ENUM_TO_STR(FLEX_BTN_PRESS_LONG_HOLD), ENUM_TO_STR(FLEX_BTN_PRESS_LONG_HOLD_UP), ENUM_TO_STR(FLEX_BTN_PRESS_MAX), ENUM_TO_STR(FLEX_BTN_PRESS_NONE), }; static char *enum_btn_id_string[] = { ENUM_TO_STR(USER_BUTTON_0), ENUM_TO_STR(USER_BUTTON_MAX), }; #endif static flex_button_t user_button[USER_BUTTON_MAX]; tmosTaskID key_task_id = INVALID_TASK_ID; volatile uint8_t key_wakeup_flag = 0; volatile uint8_t key_timeout_flag = 0; static void KEY_Task_ProcessTmosMsg(tmos_event_hdr_t *pMsg) { switch (pMsg->event) { default: logDebug("pMsg->event %04x", pMsg->event); break; } } #if 0 static uint16_t KEY_Task_ProcessEvent(uint8_t task_id, uint16_t events) { if (events & SYS_EVENT_MSG) { uint8_t *pMsg; if ((pMsg = tmos_msg_receive(key_task_id)) != NULL) { KEY_Task_ProcessTmosMsg((tmos_event_hdr_t *)pMsg); // Release the TMOS message tmos_msg_deallocate(pMsg); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } if (events & KEY_SCAN_EVT) { static volatile uint8_t key_vaild_times = 0; static volatile bool key_vaild_for_long_press = false; if (IS_KEY_Vaild()) { if (key_vaild_times > 100) { //> 20ms*100=2000ms if (false == key_vaild_for_long_press) { if (NULL != p_handler) { p_handler(kKeyLong); } // PRINT("WE should power switch here\r\n"); key_vaild_for_long_press = true; } } else { key_vaild_times++; } key_timeout_cnt = 10; } else { // button release if (key_vaild_times) { if ((key_vaild_times) < 100) { p_handler(kKeyShort); } key_vaild_times = 0; // PRINT("KEY VAILED\r\n"); } key_vaild_for_long_press = false; } if (key_timeout_cnt) { key_timeout_cnt--; tmos_start_task(key_task_id, KEY_SCAN_EVT, 64); // 40ms } else { p_handler(kKeyRelease); } return (events ^ KEY_SCAN_EVT); } // Discard unknown events return 0; } #endif // 由按键中断唤醒后开启按键扫描 void BSP_KEY_EnterLowpower(void) { key_wakeup_flag = 0; tmos_stop_task(key_task_id, KEY_SCAN_EVT); // R16_PB_INT_MODE |= KEY_B_PIN; // edge mode // GPIOB_ResetBits(KEY_B_PIN); // edge fall // R16_PB_INT_IF = KEY_B_PIN; // R16_PB_INT_EN |= KEY_B_PIN; // TODO:按键电平触发设置 // 下降沿触发 GPIOB_ITModeCfg(KEY_B_PIN, GPIO_ITMode_FallEdge); // 开启GPIO的睡眠唤醒,如果需要的话 // PWR_PeriphWakeUpCfg(ENABLE, RB_SLP_GPIO_WAKE, Long_Delay); PWR_PeriphWakeUpCfg(ENABLE, RB_GPIO_WAKE_MODE | RB_SLP_GPIO_WAKE, Long_Delay); // 开启GPIOB中断 PFIC_EnableIRQ(GPIO_B_IRQn); BSP_RequestSleep(); } void BSP_KEY_ExitLowpower(void) { BSP_BlockSleep(); // 关闭GPIOB中断 PFIC_DisableIRQ(GPIO_B_IRQn); PWR_PeriphWakeUpCfg(DISABLE, RB_GPIO_WAKE_MODE | RB_SLP_GPIO_WAKE, Long_Delay); // tmos_set_event(key_task_id, KEY_SCAN_EVT); // tmos_start_task(key_task_id, KEY_SCAN_EVT, MS1_TO_SYSTEM_TIME(30)); // tmos_start_reload_task(key_task_id, KEY_SCAN_EVT, MS1_TO_SYSTEM_TIME(30)); } __HIGH_CODE __attribute__((noinline)) void KEY_ProcessLoop(void) { // if (R16_PB_INT_IF & KEY_B_PIN) // { // R16_PB_INT_IF = KEY_B_PIN; // tmos_set_event(key_task_id, KEY_SCAN_EVT); // logDebug("KEY_ProcessLoop"); // } if (key_wakeup_flag) { key_wakeup_flag = 0; tmos_set_event(key_task_id, KEY_SCAN_EVT); // tmos_start_task(key_task_id, KEY_SCAN_EVT, MS1_TO_SYSTEM_TIME(20)); // tmos_start_task(key_task_id, KEY_IDLE_TIMEOUT_EVT, MS1_TO_SYSTEM_TIME(1000 * 10)); logDebug("key_wakeup_flag"); } } static uint8_t common_btn_read(void *arg) { uint8_t value = 0; flex_button_t *btn = (flex_button_t *)arg; switch (btn->id) { case USER_BUTTON_0: value = (uint8_t)GPIOB_ReadPortPin(KEY_B_PIN); break; default: logAssert(0, while (1)); } return value; } static void common_btn_evt_cb(void *arg) { flex_button_t *btn = (flex_button_t *)arg; logDebug("id: [%d - %s] event: [%d - %30s] repeat: %d", btn->id, enum_btn_id_string[btn->id], btn->event, enum_event_string[btn->event], btn->click_cnt); if (flex_button_event_read(&user_button[USER_BUTTON_0]) == FLEX_BTN_PRESS_CLICK) { logDebug("USER_BUTTON_0 PRESS_CLICK"); BSP_KEY_EnterLowpower(); } else if (flex_button_event_read(&user_button[USER_BUTTON_0]) == FLEX_BTN_PRESS_DOUBLE_CLICK) { logDebug("USER_BUTTON_0 PRESS_LONG_HOLD") BSP_KEY_EnterLowpower(); } else if (flex_button_event_read(&user_button[USER_BUTTON_0]) == FLEX_BTN_PRESS_LONG_START) { logDebug("USER_BUTTON_0 FLEX_BTN_PRESS_LONG_START"); BSP_KEY_EnterLowpower(); } } static uint16_t KEY_Task_ProcessEvent(uint8_t task_id, uint16_t events) { if (events & SYS_EVENT_MSG) { uint8_t *pMsg; if ((pMsg = tmos_msg_receive(key_task_id)) != NULL) { KEY_Task_ProcessTmosMsg((tmos_event_hdr_t *)pMsg); // Release the TMOS message tmos_msg_deallocate(pMsg); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } // if (events & KEY_WAKEUP_EVT) // { // logDebug("KEY_WAKEUP_EVT"); // BSP_KEY_ExitLowpower(); // return (events ^ KEY_WAKEUP_EVT); // } if (events & KEY_SCAN_EVT) { if (0 == key_timeout_flag) { if (IS_KEY_Vaild()) { tmos_stop_task(key_task_id, KEY_IDLE_TIMEOUT_EVT); tmos_start_task(key_task_id, KEY_IDLE_TIMEOUT_EVT, MS1_TO_SYSTEM_TIME(1000 * 5)); } else { logDebug("0"); } tmos_start_task(key_task_id, KEY_SCAN_EVT, MS1_TO_SYSTEM_TIME(20)); } else { logDebug("KEY_SCAN_EVT timeout"); BSP_KEY_EnterLowpower(); } // logDebug("KEY_SCAN_EVT"); flex_button_scan(); return (events ^ KEY_SCAN_EVT); } if (events & KEY_IDLE_TIMEOUT_EVT) { logDebug("KEY_IDLE_TIMEOUT_EVT"); key_timeout_flag = 1; return (events ^ KEY_IDLE_TIMEOUT_EVT); } // Discard unknown events return 0; } void BSP_KEY_Init(void) { /* 初始化按键数据结构 */ tmos_memset(&user_button[0], 0x0, sizeof(user_button)); // 由外部上拉电阻了 // 设置为浮空输入模式 GPIOB_SetBits(KEY_B_PIN); GPIOB_ModeCfg(KEY_B_PIN, GPIO_ModeIN_PU); for (uint8_t i = 0; i < USER_BUTTON_MAX; i++) { user_button[i].id = i; user_button[i].usr_button_read = common_btn_read; user_button[i].cb = common_btn_evt_cb; user_button[i].pressed_logic_level = 0; user_button[i].short_press_start_tick = FLEX_MS_TO_SCAN_CNT(1500); user_button[i].long_press_start_tick = FLEX_MS_TO_SCAN_CNT(3000); // user_button[i].long_hold_start_tick = FLEX_MS_TO_SCAN_CNT(4500); flex_button_register(&user_button[i]); } // 下降沿触发 GPIOB_ITModeCfg(KEY_B_PIN, GPIO_ITMode_FallEdge); // 开启GPIO的睡眠唤醒,如果需要的话 // PWR_PeriphWakeUpCfg(ENABLE, RB_SLP_GPIO_WAKE, Long_Delay); PWR_PeriphWakeUpCfg(ENABLE, RB_GPIO_WAKE_MODE | RB_SLP_GPIO_WAKE, Long_Delay); // 开启GPIOB中断 PFIC_EnableIRQ(GPIO_B_IRQn); key_task_id = TMOS_ProcessEventRegister(KEY_Task_ProcessEvent); // tmos_start_task(key_task_id, KEY_SCAN_EVT, MS1_TO_SYSTEM_TIME(20)); //开始一个定时事件,不断的执行,除非运行tmos_stop_task关掉, //tmosTimer具体是 1600 = 1s // tmos_start_reload_task(key_task_id, KEY_SCAN_EVT, MS1_TO_SYSTEM_TIME(20)); // BSP_KEY_EnterLowpower(); } __INTERRUPT // 告诉编译器使用硬件压栈 __HIGH_CODE // 放到RAM里 void GPIOB_IRQHandler(void) { // 阻止睡眠 BSP_BlockSleep(); // 关按键中断 BSP_KEY_ExitLowpower(); logDebug("KEY IRQ"); GPIOB_ClearITFlagBit(KEY_B_PIN); key_wakeup_flag = 1; key_timeout_flag = 0; // BSP_BlockSleep(); // if (R16_PB_INT_IF & KEY_B_PIN) // { // R16_PB_INT_IF = KEY_B_PIN; // // tmos_set_event(key_task_id, KEY_SCAN_EVT); // BSP_KEY_ExitLowpower(); // } // tmos_set_event(key_task_id,KEY_SCAN_EVT); }