#include "bsp_key.h" // #include "bsp_uart.h" #include "log.h" #include "SLEEP.h" #include "bsp_valve.h" // https://www.cnblogs.com/iot-fan/p/14304943.html #undef LOG_ENABLE #define LOG_ENABLE 1 #undef LOG_TAG #define LOG_TAG "key" tmosTaskID key_task_id = INVALID_TASK_ID; volatile uint8_t key_wakeup_flag = 0; volatile uint8_t key_timeout_flag = 0; static app_task_evt_handler_t p_handler = NULL; static volatile uint8_t key_timeout_cnt = 0; static void KEY_Task_ProcessTmosMsg(tmos_event_hdr_t *pMsg) { switch (pMsg->event) { default: logDebug("pMsg->event %04x", pMsg->event); break; } } #if 1 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 > (KEY_LONG_PRESS_MS / KEY_SACN_MS)) { //> 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 = KEY_TIMOUT_MS / KEY_SACN_MS; } else { // button release if (key_vaild_times) { if ((key_vaild_times) < (KEY_LONG_PRESS_MS / KEY_SACN_MS)) { 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--; // logDebug("key_timeout_cnt %d", key_timeout_cnt); tmos_start_task(key_task_id, KEY_SCAN_EVT, MS1_TO_SYSTEM_TIME(KEY_SACN_MS)); // 40ms } else { p_handler(kKeyRelease); } return (events ^ KEY_SCAN_EVT); } // Discard unknown events return 0; } #endif __HIGH_CODE // 由按键中断唤醒后开启按键扫描 void BSP_KEY_EnterLowpower(void) { // https://www.cnblogs.com/frontier/p/18743204 #if 1 // TODO:按键电平触发设置 // GPIOB_ModeCfg( KEY_B_PIN, GPIO_ModeIN_PU ); // 下降沿触发 GPIOB_ITModeCfg(KEY_B_PIN, GPIO_ITMode_FallEdge); // 开启GPIOB中断 PFIC_EnableIRQ(GPIO_B_IRQn); // 开启GPIO的睡眠唤醒,如果需要的话 // PWR_PeriphWakeUpCfg(ENABLE, RB_SLP_GPIO_WAKE, Long_Delay); PWR_PeriphWakeUpCfg(ENABLE, RB_GPIO_WAKE_MODE | RB_SLP_GPIO_WAKE, Long_Delay); BSP_RequestSleep(); #endif } __HIGH_CODE void BSP_KEY_ExitLowpower(void) { #if 1 BSP_BlockSleep(); // 关闭GPIOB中断 PFIC_DisableIRQ(GPIO_B_IRQn); PWR_PeriphWakeUpCfg(DISABLE, RB_GPIO_WAKE_MODE | RB_SLP_GPIO_WAKE, Long_Delay); // PWR_PeriphWakeUpCfg(DISABLE, RB_SLP_GPIO_WAKE, Long_Delay); #endif } #if 0 uint8_t read_button_GPIO(uint8_t button_id) { // you can share the GPIO read function with multiple Buttons switch(button_id) { case btn1_id: return (uint8_t)GPIOB_ReadPortPin(KEY_B_PIN); default: // logAssert(0, while (1)); return 0; } } void BTN1_PRESS_DOWN_Handler(void* btn) { logDebug("BTN1_PRESS_DOWN_Handler"); // BSP_KEY_EnterLowpower(); } void BTN1_PRESS_UP_Handler(void* btn) { logDebug("BTN1_PRESS_UP_Handler"); 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)); logDebug("tmos_start_task KEY_IDLE_TIMEOUT_EVT"); // BSP_KEY_EnterLowpower(); } void BTN1_SINGLE_Click_Handler(void* btn) { logDebug("BTN1_SINGLE_Click_Handler"); // BSP_KEY_EnterLowpower(); } void BTN1_DOUBLE_Click_Handler(void* btn) { logDebug("BTN1_DOUBLE_Click_Handler"); // BSP_KEY_EnterLowpower(); } void BTN1_LONG_PRESS_START_Handler(void* btn) { logDebug("BTN1_LONG_PRESS_START_Handler"); // 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) { tmos_start_task(key_task_id, KEY_SCAN_EVT, MS1_TO_SYSTEM_TIME(5)); } else { logDebug("KEY_SCAN_EVT timeout"); BSP_KEY_EnterLowpower(); } // logDebug("KEY_SCAN_EVT"); button_ticks(); return (events ^ KEY_SCAN_EVT); } if (events & KEY_IDLE_TIMEOUT_EVT) { tmos_stop_task(key_task_id, KEY_SCAN_EVT); BSP_KEY_EnterLowpower(); logDebug("KEY_IDLE_TIMEOUT_EVT"); key_timeout_flag = 1; return (events ^ KEY_IDLE_TIMEOUT_EVT); } // Discard unknown events return 0; } #endif void BSP_KEY_Init(app_task_evt_handler_t handler) { p_handler = handler; key_task_id = TMOS_ProcessEventRegister(KEY_Task_ProcessEvent); // // https://www.wch.cn/bbs/thread-98540-1.html // R16_PIN_ALTERNATE |= RB_PIN_INTX; // 由外部上拉电阻了 // 设置为浮空输入模式 // MCU_LDECT // GPIOA_ModeCfg(GPIO_Pin_2, GPIO_ModeIN_PU); // GPIOB_ModeCfg(GPIO_Pin_16, GPIO_ModeIN_Floating); GPIOB_ModeCfg(GPIO_Pin_16, GPIO_ModeIN_PU); GPIOB_ModeCfg(GPIO_Pin_0, GPIO_ModeIN_PU); // GPIOB_ModeCfg(GPIO_Pin_1, GPIO_ModeIN_Floating); #if 1 // 下降沿触发 GPIOB_ITModeCfg(GPIO_Pin_0, GPIO_ITMode_FallEdge); // GPIOB_ITModeCfg(GPIO_Pin_1, GPIO_ITMode_FallEdge); // 开启GPIOB中断 PFIC_EnableIRQ(GPIO_B_IRQn); // 开启GPIO的睡眠唤醒,如果需要的话 // PWR_PeriphWakeUpCfg(ENABLE, RB_SLP_GPIO_WAKE, Long_Delay); PWR_PeriphWakeUpCfg(ENABLE, RB_GPIO_WAKE_MODE | RB_SLP_GPIO_WAKE, Long_Delay); tmos_start_task(key_task_id, KEY_SCAN_EVT, MS1_TO_SYSTEM_TIME(KEY_SACN_MS)); #endif logDebug("BSP_KEY_Init=%d", IS_KEY_Vaild()); } __HIGH_CODE __attribute__((noinline)) void KEY_ProcessLoop(void) { if (key_wakeup_flag) { // 阻止睡眠 BSP_BlockSleep(); // BSP_RequestBoost(); // 关按键中断 BSP_KEY_ExitLowpower(); // PRINT("KEY IRQ\n"); // GPIOB_ClearITFlagBit(KEY_B_PIN); key_wakeup_flag = 0; tmos_set_event(key_task_id, KEY_SCAN_EVT); logDebug("KEY_ProcessLoop"); } } __INTERRUPT // 告诉编译器使用硬件压栈 __HIGH_CODE // 放到RAM里 void GPIOB_IRQHandler(void) { // // 阻止睡眠 // BSP_BlockSleep(); // // 关按键中断 // BSP_KEY_ExitLowpower(); // PRINT("KEY IRQ\n"); // GPIOB_ClearITFlagBit(KEY_B_PIN); GPIOB_ClearITFlagBit(KEY_B_PIN); // GPIOB_ClearITFlagBit(GPIO_Pin_1); // tmos_set_event(key_task_id, KEY_SCAN_EVT); // logDebug("KEY_ProcessLoop"); key_wakeup_flag = 1; }