#include "encoder_port.h" #include "cmsis_os2.h" #include "gpio.h" #include "input_manager.h" #include "pinctrl.h" #include "pm.h" #include "power_display_service.h" #include "rtc.h" #include "semaphore.h" #include "soc_errno.h" #include "sys_config.h" #include "task_driver_event.h" #include "tcxo.h" #include "time.h" #if defined(TJD_PCBA_1) #include "common_i2c.h" #include "common_pm.h" #include "encoder_drv_kth5763.h" #endif #define ENABLE_PRINT_INFO 1 #if ENABLE_PRINT_INFO #define static_print_info(...) sys_enc_log_i(__VA_ARGS__) // 一般信息打印宏控制 #define static_print_warn(...) sys_enc_log_w(__VA_ARGS__) // 警告信息打印一般常开 #define static_print_error(...) sys_enc_log_e(__VA_ARGS__) // 错误信息打印一般常开 #define static_print_debug(...) sys_enc_log_d(__VA_ARGS__) // 调试信息打印一般常开 #else #define static_print_info(...) #define static_print_warn(...) #define static_print_error(...) #define static_print_debug(...) #endif #if defined(TJD_PCBA_0) static osTimerId_t g_rotary_timer_handle; #define A_SIGNAL_PIN S_MGPIO7 #define B_SIGNAL_PIN S_MGPIO6 #endif #define REPORT_OUT_TIME_MS 155 static report_event_cb g_report_event_cb = NULL; static struct rotary_encoder g_rotary_encoder = { #if defined(TJD_PCBA_1) .i2c_bus = I2C_BUS_2, .i2c_speed = 400000, #if (CALIBRATION_MODE) .i2c_addr = KTH5701_I2C_ADDR, #else .i2c_addr = KTH5763_I2C_ADDR, #endif .int_pin = S_MGPIO9, #endif .steps = 10, .pos = 0, #if defined(TJD_PCBA_0) .gpio_descs = { .desc = {A_SIGNAL_PIN, B_SIGNAL_PIN}, .ndescs = 2, } #endif }; #if defined(TJD_PCBA_1) #define I2C_RETRY_TIMES 3 static osThreadId_t g_rotary_duty_handle = NULL; static uint8_t g_send_buf[4] = {0}; static uint8_t g_recv_buf[32] = {0}; static osThreadState_t g_rotary_duty_state = osThreadInactive; static bool g_encoder_host_dev_init_flag = false; static uint32_t get_currunt_time(void) { #define MILLISEC_TO_NANOSEC 1000000 #define SEC_TO_MILLISEC 1000 struct timespec time; clock_gettime(CLOCK_MONOTONIC, &time); return time.tv_sec * SEC_TO_MILLISEC + time.tv_nsec / MILLISEC_TO_NANOSEC; } static uint32_t get_elapse_time(uint32_t startTime) { uint32_t currentTime = get_currunt_time(); uint32_t elapseTime; if (currentTime > startTime) { elapseTime = currentTime - startTime; } else { elapseTime = (UINT32_MAX - startTime) + currentTime + 1; } return elapseTime; } static ext_errno encoder_peripheral_init_status_check(void) { if (g_encoder_host_dev_init_flag != true) { return EXT_ERR_TP_DEV_INFO_NOT_REGISTER; } return ENC_SUCC; } uint32_t encoder_i2c_cmd_write(uint8_t cmd) { const struct rotary_encoder *encoder = &g_rotary_encoder; errcode_t ret; uint8_t retry; i2c_data_t data; ret = encoder_peripheral_init_status_check(); if (ret != ENC_SUCC) { static_print_error("host peripheral not init! ret=0x%x", ret); return ret; } g_send_buf[0] = cmd; data.send_buf = g_send_buf; data.send_len = 1; data.receive_buf = NULL; data.receive_len = 0; for (retry = 0; retry < I2C_RETRY_TIMES; retry++) { ret = tjd_driver_common_i2c_get_ops()->write(I2C_MODEL_ENCODER_ID, &data); if (ret == ENC_SUCC) { break; } } if (ret != ENC_SUCC) { static_print_error("encoder data write fail! ret=0x%x", ret); return ret; } return ENC_SUCC; } uint32_t encoder_i2c_package_write(uint8_t *data_buf, uint32_t data_len) { const struct rotary_encoder *encoder = &g_rotary_encoder; errcode_t ret; uint8_t retry; ret = encoder_peripheral_init_status_check(); if (ret != 0) { static_print_error("host peripheral not init! ret=0x%x", ret); return ret; } i2c_data_t data = {.send_buf = data_buf, .send_len = data_len}; for (retry = 0; retry < I2C_RETRY_TIMES; retry++) { ret = tjd_driver_common_i2c_get_ops()->write(I2C_MODEL_ENCODER_ID, &data); if (ret == ENC_SUCC) { break; } } if (ret != ENC_SUCC) { static_print_error("encoder package write fail! ret=0x%x", ret); return ret; } return ENC_SUCC; } uint32_t encoder_i2c_reg_write(uint32_t reg_addr, uint8_t reg_len, uint8_t reg_cfg) { const struct rotary_encoder *encoder = &g_rotary_encoder; errcode_t ret; uint32_t retry; i2c_data_t data; ret = encoder_peripheral_init_status_check(); if (ret != 0) { static_print_error("host peripheral not init! ret=0x%x", ret); return ret; } reg_len = reg_len & 0x0F; memset(g_send_buf, 0, sizeof(g_send_buf)); int i = reg_len; while (i) { i--; g_send_buf[i] = reg_addr; reg_addr >>= 8; } g_send_buf[reg_len] = reg_cfg; data.send_buf = g_send_buf; data.send_len = reg_len + 1; data.receive_buf = NULL; data.receive_len = 0; for (retry = 0; retry < I2C_RETRY_TIMES; retry++) { ret = tjd_driver_common_i2c_get_ops()->write(I2C_MODEL_ENCODER_ID, &data); if (ret == ENC_SUCC) { break; } } if (ret != ENC_SUCC) { static_print_error("encoder reg write fail! ret=0x%x", ret); return ret; } return ENC_SUCC; } uint32_t encoder_i2c_data_read(uint32_t reg_addr, uint8_t reg_len, uint8_t *data_buf, uint16_t data_len) { const struct rotary_encoder *encoder = &g_rotary_encoder; errcode_t ret; uint32_t retry; i2c_data_t data; ret = encoder_peripheral_init_status_check(); if (ret != 0) { static_print_error("host peripheral not init! ret=0x%x", ret); return ret; } reg_len = reg_len & 0x0F; memset(g_send_buf, 0, sizeof(g_send_buf)); if (memset_s(g_recv_buf, data_len, 0, data_len) != EOK) { static_print_error("encoder read buff set fail! ret=0x%x", ret); return EXT_ERR_FAILURE; } int i = reg_len; while (i) { i--; g_send_buf[i] = reg_addr; reg_addr >>= 8; } data.send_buf = g_send_buf; data.send_len = reg_len; data.receive_buf = g_recv_buf; data.receive_len = data_len; for (retry = 0; retry < I2C_RETRY_TIMES; retry++) { ret = tjd_driver_common_i2c_get_ops()->writeread(I2C_MODEL_ENCODER_ID, &data); if (ret == ENC_SUCC) { break; } } if (ret != ENC_SUCC) { static_print_error("encoder reg read fail! ret=0x%x", ret); return ret; } ret = (uint32_t)memcpy_s(data_buf, data_len, g_recv_buf, data_len); if (ret != EOK) { static_print_error("encoder data buf content copy fail! ret=0x%x", ret); return ret; } return ENC_SUCC; } uint32_t encoder_i2c_data_write_read(uint8_t *send_buf, uint16_t data_len, uint8_t *recv_buf, uint16_t recv_len) { const struct rotary_encoder *encoder = &g_rotary_encoder; errcode_t ret; uint8_t retry; i2c_data_t data; ret = encoder_peripheral_init_status_check(); if (ret != 0) { static_print_error("host peripheral not init! ret=0x%x", ret); return ret; } data.send_buf = send_buf; data.send_len = data_len; data.receive_buf = g_recv_buf; data.receive_len = recv_len; for (retry = 0; retry < I2C_RETRY_TIMES; retry++) { ret = tjd_driver_common_i2c_get_ops()->writeread(I2C_MODEL_ENCODER_ID, &data); if (ret == ENC_SUCC) { break; } } if (ret != ENC_SUCC) { static_print_error("encoder package write fail! ret=0x%x", ret); return ret; } ret = (uint32_t)memcpy_s(recv_buf, recv_len, g_recv_buf, recv_len); if (ret != EOK) { static_print_error("encoder data buf content copy fail! ret=0x%x", ret); return ret; } return ENC_SUCC; } void enocder_open(void) { const struct power_manager_class_ops *power_manager_ops = tjd_driver_common_pm_get_ops(); power_manager_ops->set_model_power_status(POWER_MODEL_ENCODER_ID, PM_POWER_STATUS_ON); osDelay(80); } void enocder_close(void) { const struct power_manager_class_ops *power_manager_ops = tjd_driver_common_pm_get_ops(); // power_manager_ops->set_model_power_status(POWER_MODEL_ENCODER_ID, PM_POWER_STATUS_OFF); } #endif uint32_t encoder_register_report_event_cb(ReportEventCb callback) { if (g_report_event_cb != NULL) { return ENC_FAIL; } g_report_event_cb = callback; return ENC_SUCC; } uint32_t encoder_unregister_report_event_cb(void) { if (g_report_event_cb == NULL) { return ENC_FAIL; } g_report_event_cb = NULL; return ENC_SUCC; } static void rotary_encoder_report_event(struct rotary_encoder *encoder) { const power_display_svr_api_t *display_api = power_display_svr_get_api(); int16_t pos = encoder->pos; // static_print_debug("rotary_encoder_get_state pos:%x", pos); /* turning clockwise */ // if (pos < encoder->steps) // pos++; // encoder->pos = pos; InputDevData data = { .type = INDEV_TYPE_ENCODER, .state = 1, .rotate = pos, .timestamp = (uint32_t)uapi_tcxo_get_ms()}; if (display_api->get_screen_state() != SCREEN_ON) { return; } display_api->set_auto_timeout_function(false); if (g_report_event_cb != NULL) { g_report_event_cb(&data); } /* 释放屏幕和低功耗 */ display_api->set_auto_timeout_function(true); } void rotary_out_time_callback(void *data) { unused(data); struct rotary_encoder *encoder = &g_rotary_encoder; encoder->pos = 0; rotary_encoder_report_event(encoder); } typedef struct { signed int (*func_event_handler)(void *param); // 事件处理函数 void *param; // 事件处理函数入参 void (*func_event_debug)(char *str, ...); // 打印 void *payload; } encoder_driver_event_info_t; #if defined(TJD_PCBA_0) static void rotary_encoder_get_state(struct rotary_encoder *encoder) { static uint16_t cnt = 0; static uint16_t signal_b = 0; if (uapi_gpio_get_val(encoder->gpio_descs.desc[0]) == 0 && cnt == 0) { // A相下降沿触发第一次中断 cnt++; signal_b = 0; if (uapi_gpio_get_val(encoder->gpio_descs.desc[1]) == 1) { signal_b = 1; } } if (uapi_gpio_get_val(encoder->gpio_descs.desc[0]) == 1 && cnt == 1) { // A相上升沿触发第二次中断 cnt = 0; if (signal_b == 1 && uapi_gpio_get_val(encoder->gpio_descs.desc[1]) == 0) { encoder->pos += 1; // 正转 rotary_encoder_report_event(encoder); } else if (signal_b == 0 && uapi_gpio_get_val(encoder->gpio_descs.desc[1]) == 1) { encoder->pos -= 1; // 反转 rotary_encoder_report_event(encoder); } } } static signed int encoder_event_handler(void *param) { unused(param); const struct rotary_encoder *encoder = &g_rotary_encoder; rotary_encoder_get_state(encoder); if (osTimerIsRunning(g_rotary_timer_handle)) { osTimerStop(g_rotary_timer_handle); } osTimerStart(g_rotary_timer_handle, REPORT_OUT_TIME_MS); return 0; } static void rotary_encoder_irq(pin_t pin, uintptr_t param) { uint32_t ret = 0; static encoder_driver_event_info_t g_msg_data = { .func_event_handler = encoder_event_handler, .param = NULL, .func_event_debug = NULL, .payload = NULL, }; static unsigned int g_msg_size = sizeof(encoder_driver_event_info_t); ret = osal_msg_queue_write_copy(tjd_task_driver_event_get_queue_id(), &g_msg_data, g_msg_size, 0); if (ret != 0) { static_print_error("msg send failed! err=0x%x", ret); } } #endif #if defined(TJD_PCBA_1) struct rotary_calculate { uint16_t angle_old; uint16_t diff_angle; uint8_t power_flag : 1; uint8_t key_update_flag : 1; uint8_t key_state : 1; uint8_t last_key_state : 1; }; static void rotary_duty_task(void *arg) { unused(arg); #define ANGLE_TRESHOLD 100 struct rotary_encoder *encoder = &g_rotary_encoder; struct rotary_calculate calculate = {0}; uint16_t angle = 0; uint32_t ret = 0; uint32_t report_timer_counter = 0; g_rotary_duty_state = osThreadRunning; while (1) { uapi_pm_add_sleep_veto_with_timeout(PM_ID_ENCODER, 50); ret = kth5763_measurement(0x04, &angle); if (ret != ENC_SUCC) { static_print_error("KTH5763: measurement mode failed, %x", ret); osDelay(50); continue; } if (calculate.power_flag == 0) { calculate.power_flag = 1; calculate.angle_old = angle; } if (angle > calculate.angle_old) { if (angle < calculate.angle_old + 1800) { // 顺时针 if (angle >= calculate.angle_old + ANGLE_TRESHOLD) { calculate.diff_angle = angle - calculate.angle_old; calculate.key_update_flag = 1; // 有效旋转 calculate.key_state = 1; // 正转 calculate.angle_old = angle; } } else if (angle >= calculate.angle_old + 1800) { // 逆时针 if (3600 - angle + calculate.angle_old >= ANGLE_TRESHOLD) { calculate.diff_angle = calculate.angle_old + 3600 - angle; calculate.key_update_flag = 1; calculate.key_state = 0; // 反转 calculate.angle_old = angle; } } } else if (angle < calculate.angle_old) { if (angle + 1800 > calculate.angle_old) { if (angle + ANGLE_TRESHOLD <= calculate.angle_old) { calculate.diff_angle = calculate.angle_old - angle; calculate.key_update_flag = 1; calculate.key_state = 0; // 反转 calculate.angle_old = angle; } } else if (angle + 1800 <= calculate.angle_old) { if (3600 - calculate.angle_old + angle > ANGLE_TRESHOLD) { calculate.diff_angle = 3600 + angle - calculate.angle_old; calculate.key_update_flag = 1; calculate.key_state = 1; // 正转 calculate.angle_old = angle; } } } if (calculate.key_update_flag == 1) { /* 往相反方向转动 */ if (calculate.last_key_state != calculate.key_state) { encoder->pos = 0; } uint8_t pos_offset = (calculate.diff_angle / 100) * 1 + 1; if (calculate.key_state) { encoder->pos = 10; // 反转 } else { encoder->pos = -10; // 正转 } calculate.last_key_state = calculate.key_state; // static_print_info("encoder->pos = %d", encoder->pos); rotary_encoder_report_event(encoder); report_timer_counter = get_currunt_time(); calculate.key_update_flag = 0; } if (report_timer_counter != 0 && get_elapse_time(report_timer_counter) >= 200) { rotary_out_time_callback(NULL); report_timer_counter = 0; } osDelay(50); } } #if (CALIBRATION_MODE) void rotary_calibration_duty_task(void *arg) { struct rotary_calibration_data { uint16_t x_max; uint16_t y_max; uint16_t z_max; uint16_t x_min; uint16_t y_min; uint16_t z_min; } rotary_data = { .x_max = 32768, .y_max = 32768, .z_max = 32768, .x_min = 32768, .y_min = 32768, .z_min = 32768, }; uint16_t x_data = 0; uint16_t y_data = 0; uint16_t z_data = 0; uint8_t data[9] = {0}; uint32_t ret = 0; osDelay(100); while (1) { ret = kth5763_xyz_measurement(XYZ_MODE, data); if (ret != ENC_SUCC) { static_print_error("KTH5763: measurement mode failed, %x", ret); osDelay(50); continue; } x_data = (data[3] << 8) + data[4]; // 读取X轴输出值 y_data = (data[5] << 8) + data[6]; // 读取y轴输出值 z_data = (data[7] << 8) + data[8]; // 读取z轴输出值 static_print_info("X = %d, Y = %d, Z = %d", x_data, y_data, z_data); if (rotary_data.x_min == 0 && rotary_data.y_min == 0 && rotary_data.z_min == 0) { rotary_data.x_min = x_data; rotary_data.y_min = y_data; rotary_data.z_min = z_data; } if (rotary_data.x_max < x_data) { rotary_data.x_max = x_data; } if (rotary_data.y_max < y_data) { rotary_data.y_max = y_data; } if (rotary_data.z_max < z_data) { rotary_data.z_max = z_data; } if (rotary_data.x_min > x_data) { rotary_data.x_min = x_data; } if (rotary_data.y_min > y_data) { rotary_data.y_min = y_data; } if (rotary_data.z_min > z_data) { rotary_data.z_min = z_data; } static_print_debug("x_max = %d, y_max = %d, z_max = %d x_min = %d, y_min = %d, z_min = %d", rotary_data.x_max, rotary_data.y_max, rotary_data.z_max, rotary_data.x_min, rotary_data.y_min, rotary_data.z_min); osDelay(50); } } #endif #endif void rotary_suspend_for_i2c(void) { const struct rotary_encoder *encoder = &g_rotary_encoder; static_print_info("rotary_suspend_for_i2c %d", encoder->i2c_bus); i2c_save_reg(encoder->i2c_bus); } void rotary_resume_for_i2c(void) { const struct rotary_encoder *encoder = &g_rotary_encoder; static_print_info("rotary_resume_for_i2c %d", encoder->i2c_bus); i2c_recovery_reg(encoder->i2c_bus); } uint32_t encoder_suspend(void) { rotary_encoder_deinit(); return 0; } uint32_t encoder_resume(void) { rotary_encoder_init(NULL); return 0; } uint32_t rotary_encoder_init(struct rotary_encoder *encoder_attr) { unused(encoder_attr); uint32_t ret = 0; struct rotary_encoder *encoder = &g_rotary_encoder; /* register int io interrupt handler */ uapi_gpio_init(); uapi_pin_init(); #if defined(TJD_PCBA_1) enocder_open(); /* v1版本采用i2c方式 */ ret = tjd_driver_common_i2c_get_ops()->open(I2C_MODEL_ENCODER_ID, encoder->i2c_bus, encoder->i2c_addr, encoder->i2c_speed); if (ret != ENC_SUCC && ret != ERRCODE_I2C_ALREADY_INIT) { static_print_error("i2c master init failed, %x", ret); enocder_close(); return ENC_FAIL; } g_encoder_host_dev_init_flag = true; ret = kth5763_init(); if (ret != ENC_SUCC) { static_print_error("KTH5763: init failed, %x", ret); enocder_close(); return ENC_FAIL; } osDelay(10); osThreadAttr_t task_attr = {"tjd_encoder_task", 0, NULL, 0, NULL, 0x900, 17, 0, 0}; task_attr.stack_mem = memalign(16, task_attr.stack_size); #if (CALIBRATION_MODE) g_rotary_duty_handle = osThreadNew(rotary_calibration_duty_task, NULL, &task_attr); #else g_rotary_duty_handle = osThreadNew(rotary_duty_task, NULL, &task_attr); #endif if (g_rotary_duty_handle == NULL) { static_print_error("create rotary timer failed"); enocder_close(); return ENC_FAIL; } #endif #if defined(TJD_PCBA_0) g_rotary_timer_handle = osTimerNew((osTimerFunc_t)rotary_out_time_callback, osTimerOnce, 0, NULL); if (g_rotary_timer_handle == NULL) { static_print_error("create rotary timer failed"); return ENC_FAIL; } for (int i = 0; i < encoder->gpio_descs.ndescs; ++i) { uapi_pin_set_mode(encoder->gpio_descs.desc[i], HAL_PIO_FUNC_GPIO); uapi_pin_set_pull(encoder->gpio_descs.desc[i], HAL_PIO_PULL_UP); uapi_gpio_set_dir(encoder->gpio_descs.desc[i], GPIO_DIRECTION_INPUT); } uapi_tcxo_delay_ms(5); ret = uapi_gpio_register_isr_func(encoder->gpio_descs.desc[0], GPIO_INTERRUPT_DEDGE, rotary_encoder_irq); if (ret != ENC_SUCC) { static_print_error("register isr func failed, %x", ret); return ret; } uapi_tcxo_delay_ms(5); ret = uapi_gpio_enable_interrupt(encoder->gpio_descs.desc[0]); if (ret != ENC_SUCC) { static_print_error("enable interrupt failed, %x", ret); return ret; } #endif static_print_info("rotary encoder init success"); return ENC_SUCC; } uint32_t rotary_encoder_deinit(void) { uint32_t ret = 0; #if defined(TJD_PCBA_0) uapi_gpio_disable_interrupt(g_rotary_encoder.gpio_descs.desc[0]); uapi_gpio_unregister_isr_func(g_rotary_encoder.gpio_descs.desc[0]); #endif #if defined(TJD_PCBA_1) if (g_rotary_duty_handle == NULL) { return ENC_SUCC; } if (g_rotary_duty_state == osThreadRunning) { if (osThreadTerminate(g_rotary_duty_handle) != osOK) { static_print_error("terminate rotary task failed"); } g_rotary_duty_state = osThreadInactive; } osDelay(25); kth5763_enter_idle(); tjd_driver_common_i2c_get_ops()->close(I2C_MODEL_ENCODER_ID); g_encoder_host_dev_init_flag = false; static_print_info("rotary encoder deinit success"); #endif enocder_close(); return ENC_SUCC; }