368 lines
11 KiB
C
368 lines
11 KiB
C
#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
|