#include "include.h" #include "bsp_sys.h" #define TRACE_EN 0 #if TRACE_EN #define TRACE(...) printf(__VA_ARGS__) #else #define TRACE(...) #endif #if USER_KEY_QDEC_EN #define QDEC_ORIGINAL_PLAN_EN 0 #if !QDEC_ORIGINAL_PLAN_EN #define QDEC_PRESSED_CNT_MAX 3 #define QDEC_DEBOUNCE_CNT_MAX 5 typedef struct { bool back_pressed; // 检测释放 uint32_t back_pressed_cnt; // 释放消抖次数 uint32_t back_debounce_cnt; // 按下消抖次数 bool for_pressed; // 检测释放 uint32_t for_pressed_cnt; // 释放消抖次数 uint32_t for_debounce_cnt; // 按下消抖次数 } qdec_button_t; static qdec_button_t qdec_button = {0}; AT(.com_text.qdec) static void qdec_key_for_clear(void) { qdec_button.for_pressed = false; qdec_button.for_pressed_cnt = 0; qdec_button.for_pressed_cnt = 0; } AT(.com_text.qdec) static void qdec_key_back_clear(void) { qdec_button.back_pressed = false; qdec_button.back_pressed_cnt = 0; qdec_button.back_debounce_cnt = 0; } AT(.com_text.qdec) void qdec_key_msg_enqueue(u8 msg) { static u32 interrupt_time = 0; if (tick_check_expire(interrupt_time, 30)) { interrupt_time = tick_get(); reset_sleep_delay_all(); // 复位休眠计数 my_msg_enqueue(msg); } } AT(.com_text.qdec) void bsp_qdec_process(void) { bool forward_state = false; bool backward_state = false; #if (USER_QDEC_MAPPING == QDEC_MAP_G1) forward_state = !(GPIOB & BIT(1)) ? false : true; backward_state = !(GPIOB & BIT(0)) ? false : true; #elif (USER_QDEC_MAPPING == QDEC_MAP_G2) forward_state = !(GPIOE & BIT(2)) ? false : true; backward_state = !(GPIOE & BIT(1)) ? false : true; #elif (USER_QDEC_MAPPING == QDEC_MAP_G3) forward_state = !(GPIOE & BIT(7)) ? false : true; backward_state = !(GPIOE & BIT(6)) ? false : true; #endif /* BACKWARD */ if (!backward_state) { if (qdec_button.back_debounce_cnt < QDEC_DEBOUNCE_CNT_MAX) { qdec_button.back_debounce_cnt++; } else { if (!qdec_button.back_pressed) { qdec_button.back_pressed_cnt = 0; qdec_button.back_pressed = true; } else { /* 编码器处于长触发未释放状态 */ qdec_key_for_clear(); } } } else { qdec_button.back_debounce_cnt = 0; if (qdec_button.back_pressed) { if (++qdec_button.back_pressed_cnt > QDEC_PRESSED_CNT_MAX) { qdec_key_back_clear(); qdec_key_msg_enqueue(MSG_QDEC_BACKWARD); } qdec_key_for_clear(); } } /* FORWARD */ if (!forward_state) { if (qdec_button.for_debounce_cnt < QDEC_DEBOUNCE_CNT_MAX) { qdec_button.for_debounce_cnt++; } else { if (!qdec_button.for_pressed) { qdec_button.for_pressed_cnt = 0; qdec_button.for_pressed = true; } else { /* 编码器处于长触发未释放状态 */ qdec_key_back_clear(); } } } else { qdec_button.for_debounce_cnt = 0; if (qdec_button.for_pressed) { if (++qdec_button.for_pressed_cnt > QDEC_PRESSED_CNT_MAX) { qdec_key_for_clear(); qdec_key_msg_enqueue(MSG_QDEC_FORWARD); } qdec_key_back_clear(); } } } #else AT(.com_text.qdec) void qdec_key_msg_enqueue(u8 msg) { /* 硬件正交解码额外消抖间隔时长 (unit:ms) */ static u32 interrupt_time = 0; if (tick_check_expire(interrupt_time, 30)) { interrupt_time = tick_get(); reset_sleep_delay_all(); // 复位休眠计数 my_msg_enqueue(msg); } } /* * 旋转编码器Quadrate Decode * QDEC_MAP_G1: A -> PB0, B -> PB1 * QDEC_MAP_G2: A -> PE1, B -> PE2 * QDEC_MAP_G3: A -> PE6, B -> PE7 */ AT(.com_text.qdec) void qdec_isr(void) { u32 qdeccon = QDECCON; if (qdeccon & BIT(1)) { //interrupt is enbale? if (qdeccon & BIT(30)) { //forward QDECCPND = BIT(30); qdec_key_msg_enqueue(MSG_QDEC_BACKWARD); } if (qdeccon & BIT(31)) { //reverse QDECCPND = BIT(31); qdec_key_msg_enqueue(MSG_QDEC_FORWARD); } } } AT(.com_text.qdec) void bsp_qdec_process(void) { } #endif void bsp_qdec_init(void) { CLKGAT2 |= BIT(2); //qdec clk enable #if (USER_QDEC_MAPPING == QDEC_MAP_G1) GPIOBDIR |= 0x03; GPIOBDE |= 0x03; GPIOBFEN |= 0x03; GPIOBPU |= 0x03; #elif (USER_QDEC_MAPPING == QDEC_MAP_G2) GPIOEDIR |= 0x06; GPIOEDE |= 0x06; GPIOEFEN |= 0x06; GPIOEPU |= 0x06; #elif (USER_QDEC_MAPPING == QDEC_MAP_G3) GPIOEDIR |= 0xc0; GPIOEDE |= 0xc0; GPIOEFEN |= 0xc0; GPIOEPU |= 0xc0; #endif #if QDEC_ORIGINAL_PLAN_EN sys_irq_init(IRQ_QDEC_VECTOR, 0, qdec_isr); FUNCMCON2 = USER_QDEC_MAPPING; QDECCON = 63 << 3; //quadrate decode filter length QDECCPND = BIT(30) | BIT(31); QDECCON = BIT(0) | BIT(1); //qdec decode enable, interrupt enable #endif } #elif USER_ADKEY_QDEC_EN /* * QDEC_A串接5.1K,QEC_B串接10K,接到同一IO上。IO开内部10K上拉,用ADC来采电压。 * 正旋:3.3v -- 1.113v -- 0.825v -- 1.65v -- 3.3v * 正旋: AH_BH - AL_BH -- AL_BL -- AH_BL -- AH_BH * 反旋:3.3v -- 1.65v -- 0.825v -- 1.113v -- 3.3v * 反旋:AH_BH - AH_BL -- AL_BL -- AL_BH -- AH_BH */ enum { QEC_AH_BH, //A输出高电平,B输出高电平,空闲状态 QEC_AL_BH, //A输出低电平,B输出高电平 QEC_AL_BL, //A输出低电平,B输出低电平 QEC_AH_BL, //A输出高电平,B输出低电平 }; typedef struct { u8 status[3]; u8 cnt; u8 pre_sta; u8 new_sta; u8 new_sta_cnt; } qdec_cb_t; static qdec_cb_t qdec_cb; AT(.com_rodata.pwrkey.table) const adkey_tbl_t qdec_adkey_table[6] = { {0x30, QEC_AH_BH}, {0x4C, QEC_AL_BL}, {0x6A, QEC_AL_BH}, {0x8A, QEC_AH_BL}, {0xFF, QEC_AH_BH}, }; void bsp_qdec_init(void) { u8 io_num = get_adc_gpio_num(USER_QDEC_ADCH); memset(&qdec_cb, 0, sizeof(qdec_cb_t)); if (io_num != IO_NONE) { gpio_t gpio; gpio_cfg_init(&gpio, io_num); gpio.sfr[GPIOxDE] |= gpio.pin; gpio.sfr[GPIOxDIR] |= gpio.pin; gpio.sfr[GPIOxPU] |= gpio.pin; saradc_set_channel(BIT(USER_QDEC_ADCH)); } } AT(.com_text.qdec) void qdec_key_msg_enqueue(u8 msg) { reset_sleep_delay_all(); //复位休眠计数 my_msg_enqueue(msg); } #if TRACE_EN AT(.com_text.str) char qdec_str0[] = "(qdec)%d->%d[%d %d %d]\n"; AT(.com_text.str) char qdec_str1[] = "(qdec)[%d %d %d]\n"; AT(.com_text.str) char qdec_str2[] = "(qdec)[%d %d %d]!!!!!\n"; AT(.com_text.str) char qdec_str3[] = "(qdec)0x%x\n"; #endif // TRACE_EN //每毫秒ADC采样值进行处理 AT(.com_text.qdec) void bsp_qdec_adc_process(u8 adc_val) { u8 num = 0; u8 qdec_cur_sta; while ((u8)adc_val > qdec_adkey_table[num].adc_val) { num++; } qdec_cur_sta = qdec_adkey_table[num].usage_id; if (qdec_cb.new_sta) { //消抖 if (qdec_cb.new_sta == qdec_cur_sta) { qdec_cb.new_sta_cnt++; if (qdec_cb.new_sta_cnt >= 1) { //增大该值以提高消抖程度 qdec_cb.new_sta = 0; qdec_cb.new_sta_cnt = 0; if (qdec_cur_sta != qdec_cb.pre_sta) { if (qdec_cur_sta != QEC_AH_BH) { if (qdec_cb.pre_sta == QEC_AH_BH) { qdec_cb.cnt = 0; } if (qdec_cb.cnt < 3) { qdec_cb.status[qdec_cb.cnt++] = qdec_cur_sta; } } TRACE(qdec_str0, qdec_cb.pre_sta , qdec_cur_sta, qdec_cb.status[0], qdec_cb.status[1], qdec_cb.status[2]); qdec_cb.pre_sta = qdec_cur_sta; } } } else { qdec_cb.new_sta = qdec_cur_sta; qdec_cb.new_sta_cnt = 0; } } else if (qdec_cur_sta != qdec_cb.pre_sta) { qdec_cb.new_sta = qdec_cur_sta; qdec_cb.new_sta_cnt = 0; } if (qdec_cur_sta == QEC_AH_BH) { //结束 #if !USER_ADKEY_QDEC_NO_STD if (qdec_cb.cnt == 3 && qdec_cb.status[1] == QEC_AL_BL) { TRACE(qdec_str1, qdec_cb.status[0], qdec_cb.status[1], qdec_cb.status[2]); if (qdec_cb.status[0] == QEC_AL_BH && qdec_cb.status[2] == QEC_AH_BL) { qdec_key_msg_enqueue(MSG_QDEC_FORWARD); // uart_putchar('F'); } else if (qdec_cb.status[2] == QEC_AL_BH && qdec_cb.status[0] == QEC_AH_BL) { qdec_key_msg_enqueue(MSG_QDEC_BACKWARD); // uart_putchar('R'); } } else if (qdec_cb.cnt >= 1) { TRACE(qdec_str2, qdec_cb.status[0], qdec_cb.status[1], qdec_cb.status[2]); } #else if (qdec_cb.status[1] == QEC_AL_BL) { if (qdec_cb.status[0] == QEC_AL_BH) { #if defined(SETTING_MSG_QDEC_WARD) qdec_key_msg_enqueue(MSG_QDEC_FORWARD); #else qdec_key_msg_enqueue(MSG_QDEC_BACKWARD); #endif // uart_putchar('F'); if (qdec_cb.cnt == 3 && qdec_cb.status[2] == QEC_AH_BL) { TRACE(qdec_str1, qdec_cb.status[0], qdec_cb.status[1], qdec_cb.status[2]); } else { TRACE(qdec_str2, qdec_cb.status[0], qdec_cb.status[1], qdec_cb.status[2]); } } else if (qdec_cb.status[0] == QEC_AH_BL) { #if defined(SETTING_MSG_QDEC_WARD) qdec_key_msg_enqueue(MSG_QDEC_BACKWARD); #else qdec_key_msg_enqueue(MSG_QDEC_FORWARD); #endif // uart_putchar('R'); if (qdec_cb.cnt == 3 && qdec_cb.status[2] == QEC_AL_BH) { TRACE(qdec_str1, qdec_cb.status[0], qdec_cb.status[1], qdec_cb.status[2]); } else { TRACE(qdec_str2, qdec_cb.status[0], qdec_cb.status[1], qdec_cb.status[2]); } } else { TRACE(qdec_str2, qdec_cb.status[0], qdec_cb.status[1], qdec_cb.status[2]); } } else if (qdec_cb.cnt >= 1) { TRACE(qdec_str2, qdec_cb.status[0], qdec_cb.status[1], qdec_cb.status[2]); } #endif memset(&qdec_cb, 0, sizeof(qdec_cb_t)); } } #else void bsp_qdec_init(void) { } #endif // USER_ADKEY_QDEC_EN