327 lines
9.1 KiB
C
Raw Normal View History

2025-02-18 15:40:42 +08:00
#include "system/includes.h"
#include "code_switch.h"
#include "app_config.h"
#include "stdlib.h"
#if TCFG_CODE_SWITCH_ENABLE
#if 1
#define log_debug printf
#else
#define log_debug(...)
#endif
#define INPUT_CHANNLE6_SRC_SEL(x) SFR(JL_IOMAP->CON4, 16, 6, x)
#define INPUT_CHANNLE7_SRC_SEL(x) SFR(JL_IOMAP->CON4, 24, 6, x)
static SW_PLATFORM_DATA *sw_pdata = NULL;
static u8 code_switch_active = 0;
static void code_switch_event_to_usr(u8 event, s8 sw_val);
static void get_code_value_handler(void *priv);
/* static void get_code_value_handler(void); */
static u8 code_switch_idle_query(void);
static void code_switch_event_to_usr(u8 event, s8 sw_val)
{
struct sys_event e;
e.type = SYS_DEVICE_EVENT;
e.arg = "code_switch";
e.u.codesw.event = event;
e.u.codesw.value = sw_val;
sys_event_notify(&e);
}
/* ___interrupt */
/* static void get_code_value_handler(void) */
/* { */
/* if (JL_RDEC->CON & 0x80) */
/* { */
/* mouse_code_switch_event_to_usr(0, JL_RDEC->DAT); */
/* JL_RDEC->CON |= BIT(6); */
/* } */
/* } */
/* */
u8 code_postive_list[] = {
((0x00 << 4) | (0x02 << 2) | (0x03 << 0)), \
((0x00 << 4) | (0x02 << 2) | (0x01 << 0)), \
((0x00 << 4) | (0x03 << 2) | (0x01 << 0)), \
((0x02 << 4) | (0x03 << 2) | (0x01 << 0)), \
((0x02 << 4) | (0x03 << 2) | (0x00 << 0)), \
((0x02 << 4) | (0x01 << 2) | (0x00 << 0)), \
((0x03 << 4) | (0x01 << 2) | (0x00 << 0)), \
((0x03 << 4) | (0x01 << 2) | (0x02 << 0)), \
((0x03 << 4) | (0x00 << 2) | (0x02 << 0)), \
((0x01 << 4) | (0x00 << 2) | (0x02 << 0)), \
((0x01 << 4) | (0x00 << 2) | (0x03 << 0)), \
((0x01 << 4) | (0x02 << 2) | (0x03 << 0))
};
u8 code_negative_list[] = {
((0x00 << 4) | (0x01 << 2) | (0x03 << 0)), \
((0x00 << 4) | (0x01 << 2) | (0x02 << 0)), \
((0x00 << 4) | (0x03 << 2) | (0x02 << 0)), \
((0x01 << 4) | (0x03 << 2) | (0x02 << 0)), \
((0x01 << 4) | (0x03 << 2) | (0x00 << 0)), \
((0x01 << 4) | (0x02 << 2) | (0x00 << 0)), \
((0x03 << 4) | (0x02 << 2) | (0x00 << 0)), \
((0x03 << 4) | (0x02 << 2) | (0x01 << 0)), \
((0x03 << 4) | (0x00 << 2) | (0x01 << 0)), \
((0x02 << 4) | (0x00 << 2) | (0x01 << 0)), \
((0x02 << 4) | (0x00 << 2) | (0x03 << 0)), \
((0x02 << 4) | (0x01 << 2) | (0x03 << 0))
};
//功能:相位纠正
static void correct_code(u8 *code_data, u8 *list_data, u8 idx)
{
code_data[2] = (list_data[(idx / 3) * 3] & (0x03 << 4)) >> 4;
code_data[1] = (list_data[(idx / 3) * 3] & (0x03 << 2)) >> 2;
code_data[0] = (list_data[(idx / 3) * 3] & (0x03 << 0)) >> 0;
log_debug("lost_phase_recover: %d %d %d\n", code_data[2], code_data[1], code_data[0]);
}
//功能:相位遍历
static u8 traverse_phase_list(u8 *code_data, u8 *list_data, u8 size)
{
u8 code_num = 0, idx = 0;
code_num = code_data[2] << 4 | code_data[1] << 2 | code_data[0] << 0;
for (idx = 0; idx < size; idx++) {
if (code_num == list_data[idx]) {
if (idx % 3) {
/* correct_code(code_data, list_data, idx); */
}
break;
}
}
return idx;
}
//功能:消抖
static bool code_phase_debounce(u8 code_val)
{
static u8 filter_value = 0, filter_cnt = 0;
const u8 filter_time = 2;
//当前值与上一次值如果不相等, 重新消抖处理, 注意filter_time != 0;
if (code_val != filter_value && filter_time) {
filter_cnt = 0; //消抖次数清0, 重新开始消抖
filter_value = code_val;//记录上一次的值
return false; //第一次检测, 返回不做处理
}
//当前值与上一次值相等, filter_cnt开始累加;
if (filter_cnt < filter_time) {
filter_cnt++;
return false;
}
return true;
}
//功能:获取相位
static bool get_code_phase(u8 *code_data)
{
static u8 code_now = 0, code_last = 0;
static u8 debug_count = 0;
//获取相位值
code_last = code_now;
code_now = (gpio_read(sw_pdata->a_phase_io) ? 0x02 : 0x00) + (gpio_read(sw_pdata->b_phase_io) ? 0x01 : 0x00);
//相位状态出现变化,将相位值存入队列
if (code_last != code_now && code_now != code_data[0]) {
code_data[2] = code_data[1];
code_data[1] = code_data[0];
code_data[0] = code_now;
code_switch_active = 200;//编码开关工作状态标志位
/* log_debug(">>>%d<<<%d %d %d\n", debug_count, code_data[2], code_data[1], code_data[0]); */
debug_count++;
return true;
}
//相位状态无变化,编码开关工作状态标志位递减
else {
if (code_switch_active) {
code_switch_active--;
}
}
return false;
}
//功能:获取编码值
u8 get_code_value(u8 *code_data)
{
u8 idx = 0; //相位序列号
static u8 code_val = 0;
static u8 move_now = 0, move_last = 0;
static u8 idx_pos_last = 0, idx_neg_last = 0;
enum {
MOVE_POS,
MOVE_NEG,
};
//正相位遍历,获取相位序列号
idx = traverse_phase_list(code_data, &code_postive_list[0], ARRAY_SIZE(code_postive_list));
//相位序列号有效,则出现正向滚动动作
if (idx < ARRAY_SIZE(code_postive_list)) {
move_last = move_now;
move_now = MOVE_POS;
//相位区域限制,避免重复检测
if ((idx >= 0 && idx <= 2) || (idx >= 6 && idx <= 8) || (move_now != move_last))
/* if (abs(idx_pos_last/3-idx/3)>=2 || (move_now != move_last)) */
{
code_val++; //正向滚动,编码值+1
idx_pos_last = idx;
/* log_debug(">>>>>>>>>>>>>>>>>>>>>>>idx = %d R\n", idx); */
/* log_debug("\n"); */
return code_val;
}
}
//负相位遍历,获取相位序列号
idx = traverse_phase_list(code_data, &code_negative_list[0], ARRAY_SIZE(code_negative_list));
//相位序列号有效,则出现负向滚动
if (idx < ARRAY_SIZE(code_negative_list)) {
move_last = move_now;
move_now = MOVE_NEG;
//相位区域限制,避免重复检测
if ((idx >= 3 && idx <= 5) || (idx >= 9 && idx <= 11) || (move_now != move_last))
/* if (abs(idx_neg_last/3-idx/3)>=2 || (move_now != move_last)) */
{
code_val--; //负向滚动,编码值-1
idx_neg_last = idx;
/* log_debug(">>>>>>>>>>>>>>>>>>>>>>>idx = %d L\n", idx); */
/* log_debug("\n"); */
return code_val;
}
}
return code_val;
}
//功能:旋转编码开关检测
static u8 code_switch_detector(void)
{
static u8 code_table[3] = {0}; //相位值存储队列
static u8 code_val = 0;
//相位有变化,进行相位遍历,获取编码值
if (get_code_phase(&code_table[0])) {
code_val = get_code_value(&code_table[0]);
}
//相位无变化,编码值保持不变
else {
code_val = code_val;
}
return code_val;
}
//功能:旋转编码开关数据采集
static void code_switch_handler(void *priv)
{
static u8 code_val_last = 0;
static u8 code_val_now = 0;
code_val_last = code_val_now;
code_val_now = code_switch_detector();
if (code_val_last != code_val_now) {
code_switch_event_to_usr(0, code_val_now - code_val_last);
}
/* if (JL_RDEC->DAT != code) */
/* { */
/* code_switch_event_to_usr(0, JL_RDEC->DAT - code); */
/* code_switch_active = 10; */
/* } */
/* */
/* else */
/* { */
/* code_switch_active--; */
/* } */
/* */
/* code = JL_RDEC->DAT; */
/* pnd = JL_RDEC->CON & 0x80; */
/* if (pnd) */
/* { */
/* code_switch_event_to_usr(0, JL_RDEC->DAT); */
/* JL_RDEC->CON |= BIT(6); */
/* putchar('Y'); */
/* CODE_IO_DEBUG_TOGGLE(A,2) */
/* } */
}
void code_switch_init(SW_PLATFORM_DATA *priv)
{
sw_pdata = priv;
/* JL_RDEC->CON |= BIT(0); //Enable RDEC */
/* JL_RDEC->CON &= ~BIT(1);//pull up */
/* JL_RDEC->CON |= 15<<2; */
/* JL_IOMAP->CON1 &= ~BIT(12); //RDES_IOSO = PB4 */
/* JL_IOMAP->CON1 &= ~BIT(13); //RDES_IOS1 = PB5 */
/* JL_IOMAP->CON1 |= BIT(12); */
/* JL_IOMAP->CON1 |= BIT(13); */
/* INPUT_CHANNLE6_SRC_SEL(sw_pdata->a_phase_io); */
/* INPUT_CHANNLE7_SRC_SEL(sw_pdata->b_phase_io); */
gpio_set_die(sw_pdata->a_phase_io, 1);
gpio_set_dieh(sw_pdata->a_phase_io, 1);
gpio_set_direction(sw_pdata->a_phase_io, 1);
gpio_set_pull_up(sw_pdata->a_phase_io, 0);
gpio_set_pull_down(sw_pdata->a_phase_io, 0);
gpio_set_die(sw_pdata->b_phase_io, 1);
gpio_set_dieh(sw_pdata->b_phase_io, 1);
gpio_set_direction(sw_pdata->b_phase_io, 1);
gpio_set_pull_up(sw_pdata->b_phase_io, 0);
gpio_set_pull_down(sw_pdata->b_phase_io, 0);
/* request_irq(IRQ_RDEC_IDX, 3, code_switch_handler, 0); */
sys_s_hi_timer_add(NULL, code_switch_handler, 2); //10ms
}
static u8 code_switch_idle_query(void)
{
/* return !(JL_RDEC->CON & 0x80); */
return (!code_switch_active);
}
REGISTER_LP_TARGET(code_switch_lp_target) = {
.name = "code_switch",
.is_idle = code_switch_idle_query,
};
#endif /* CODE_SWITCH_ENABLE */