327 lines
9.1 KiB
C
327 lines
9.1 KiB
C
|
#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 */
|