From a719db1b58bcc57a280a85340de13894e49bd984 Mon Sep 17 00:00:00 2001 From: fangpeina Date: Fri, 11 Oct 2024 22:38:55 +0800 Subject: [PATCH] drivers/input: support RTP file simulation in RAMLOOP mode For resource-constrained devices, simulate RTP playback effects using preset custom RAMLOOP combinations instead of using RTP files to play custom vibration effects. Signed-off-by: fangpeina --- drivers/input/Kconfig | 13 ++- drivers/input/aw86225.c | 140 ++++++++++++++++++++++++------- drivers/input/aw86225_internal.h | 1 + include/nuttx/input/aw86225.h | 13 +++ 4 files changed, 136 insertions(+), 31 deletions(-) diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 4c1100ffb32..959b9e0cda4 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -46,13 +46,22 @@ config FF_AW86225 ---help--- Enable aw86225 haptic controller chip. -config FF_RTP_FILE_PATH +if FF_AW86225 + +config AW86225_RTP_FILE_SUPPORT + bool "Enable aw86225 rtp file support" + default n + ---help--- + Enable support for aw86225 rtp file. + +config AW86225_RTP_FILE_PATH string "Path of aw86225 rtp file" default "/etc" - depends on FF_AW86225 ---help--- File path depend on the opening of FF_AW86225. +endif # FF_AW86225 + endif # INPUT_FF config INPUT_MOUSE diff --git a/drivers/input/aw86225.c b/drivers/input/aw86225.c index 3816fe3003d..41a1ee54924 100644 --- a/drivers/input/aw86225.c +++ b/drivers/input/aw86225.c @@ -64,6 +64,7 @@ static void aw86225_ram_work_routine(FAR void *arg); ****************************************************************************/ static FAR const char *g_aw86225_ram_name = "aw86225_haptic.bin"; +#ifdef CONFIG_AW86225_RTP_FILE_SUPPORT static FAR const char g_aw86225_rtp_name[][AW86225_RTP_NAME_MAX] = { {"door_open_RTP.bin"}, @@ -240,6 +241,7 @@ static FAR const char g_aw86225_rtp_name[][AW86225_RTP_NAME_MAX] = {"signal_transition_rtp.bin"}, {"haptics_video_rtp.bin"}, }; +#endif /**************************************************************************** * Private Functions @@ -334,6 +336,7 @@ static int aw86225_i2c_read(FAR struct aw86225 *aw86225, uint8_t reg_addr, return aw86225_i2c_read_cnt(aw86225, reg_addr, reg_data, 1); } +#ifdef CONFIG_AW86225_RTP_FILE_SUPPORT static int aw86225_i2c_writes(FAR struct aw86225 *aw86225, unsigned char reg_addr, FAR unsigned char *buf, @@ -341,6 +344,7 @@ static int aw86225_i2c_writes(FAR struct aw86225 *aw86225, { return aw86225_i2c_write_cnt(aw86225, reg_addr, buf, len); } +#endif static int aw86225_i2c_write_bits(FAR struct aw86225 *aw86225, unsigned char reg_addr, unsigned int mask, @@ -381,8 +385,8 @@ static int aw86225_request_firmware(FAR struct aw86225_firmware *fw, return -ENOMEM; } - snprintf(file_path, PATH_MAX, "%s/%s", CONFIG_FF_RTP_FILE_PATH, - filename); + snprintf(file_path, PATH_MAX, "%s/%s", + CONFIG_AW86225_RTP_FILE_PATH, filename); ret = file_open(&file, file_path, O_RDONLY); lib_put_pathbuffer(file_path); if (ret < 0) @@ -418,32 +422,6 @@ static void aw86225_release_firmware(FAR struct aw86225_firmware *fw) fw->size = 0; } -static uint8_t aw86225_haptic_rtp_get_fifo_afs(FAR struct aw86225 *aw86225) -{ - uint8_t reg_val = 0; - - aw86225_i2c_read(aw86225, AW86225_REG_SYSST, ®_val); - reg_val &= AW86225_BIT_SYSST_FF_AFS; - return reg_val >> 3; -} - -static void aw86225_haptic_set_rtp_aei(FAR struct aw86225 *aw86225, - bool flag) -{ - if (flag) - { - aw86225_i2c_write_bits(aw86225, AW86225_REG_SYSINTM, - AW86225_BIT_SYSINTM_FF_AEM_MASK, - AW86225_BIT_SYSINTM_FF_AEM_ON); - } - else - { - aw86225_i2c_write_bits(aw86225, AW86225_REG_SYSINTM, - AW86225_BIT_SYSINTM_FF_AEM_MASK, - AW86225_BIT_SYSINTM_FF_AEM_OFF); - } -} - static void aw86225_haptic_upload_lra(FAR struct aw86225 *aw86225, unsigned int flag) { @@ -758,6 +736,14 @@ static int aw86225_haptic_set_wav_loop(FAR struct aw86225 *aw86225, return 0; } +static int aw86225_haptic_set_main_loop(FAR struct aw86225 *aw86225, + uint8_t loop) +{ + aw86225_i2c_write_bits(aw86225, AW86225_REG_WAVCFG13, + AW86225_BIT_WAVCFG13_MAINLOOP_MASK, loop); + return 0; +} + static int aw86225_haptic_read_lra_f0(FAR struct aw86225 *aw86225) { unsigned char reg_val = 0; @@ -934,6 +920,33 @@ static int aw86225_haptic_cont_get_f0(FAR struct aw86225 *aw86225) return ret; } +#ifdef CONFIG_AW86225_RTP_FILE_SUPPORT +static uint8_t aw86225_haptic_rtp_get_fifo_afs(FAR struct aw86225 *aw86225) +{ + uint8_t reg_val = 0; + + aw86225_i2c_read(aw86225, AW86225_REG_SYSST, ®_val); + reg_val &= AW86225_BIT_SYSST_FF_AFS; + return reg_val >> 3; +} + +static void aw86225_haptic_set_rtp_aei(FAR struct aw86225 *aw86225, + bool flag) +{ + if (flag) + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_SYSINTM, + AW86225_BIT_SYSINTM_FF_AEM_MASK, + AW86225_BIT_SYSINTM_FF_AEM_ON); + } + else + { + aw86225_i2c_write_bits(aw86225, AW86225_REG_SYSINTM, + AW86225_BIT_SYSINTM_FF_AEM_MASK, + AW86225_BIT_SYSINTM_FF_AEM_OFF); + } +} + static int aw86225_haptic_rtp_init(FAR struct aw86225 *aw86225) { unsigned int buf_len = 0; @@ -1009,6 +1022,7 @@ static int aw86225_haptic_rtp_init(FAR struct aw86225 *aw86225) iinfo("%s exit\n", __func__); return 0; } +#endif static int aw86225_haptic_set_repeat_wav_seq(FAR struct aw86225 *aw86225, unsigned char seq) @@ -1080,6 +1094,7 @@ aw86225_haptic_effect_strength(FAR struct aw86225 *aw86225) return 0; } +#ifdef CONFIG_AW86225_RTP_FILE_SUPPORT static void aw86225_rtp_work_routine(FAR void *arg) { FAR struct aw86225 *aw86225 = arg; @@ -1243,6 +1258,7 @@ static void aw86225_rtp_work_routine(FAR void *arg) nxmutex_unlock(&aw86225->lock); } } +#endif static int aw86225_container_update(FAR struct aw86225 *aw86225, FAR struct aw86225_container *aw86225_cont) @@ -1677,7 +1693,16 @@ static int aw86225_haptic_start(FAR struct aw86225 *aw86225) static int aw86225_haptic_play_effect_seq(FAR struct aw86225 *aw86225, unsigned char flag) { - if (aw86225->effect_id > aw86225->config->effect_id_boundary) + if ((aw86225->activate_mode == AW86225_HAPTIC_ACTIVATE_RAM_MODE || + aw86225->activate_mode == AW86225_HAPTIC_ACTIVATE_RAM_LOOP_MODE) && + aw86225->effect_id > aw86225->config->effect_id_boundary) + { + return 0; + } + + if (aw86225->activate_mode == AW86225_HAPTIC_ACTIVATE_RTP_MODE && + (aw86225->effect_id > aw86225->config->effect_max || + aw86225->effect_id < aw86225->config->effect_id_boundary)) { return 0; } @@ -1725,6 +1750,33 @@ static int aw86225_haptic_play_effect_seq(FAR struct aw86225 *aw86225, aw86225_haptic_set_gain(aw86225, aw86225->level); aw86225_haptic_play_repeat_seq(aw86225, true); } + + if (aw86225->activate_mode == AW86225_HAPTIC_ACTIVATE_RTP_MODE) + { + int budry = aw86225->effect_id - + aw86225->config->effect_id_boundary; + iinfo("budry = %d\n", budry); + for (uint8_t i = 0; i < 8; i++) + { + iinfo("wav_seq[%d] = %d\n", i, + aw86225->pattern[budry].patternid[i]); + iinfo("wav_loop[%d] = %d\n", i, + aw86225->pattern[budry].waveloop[i]); + aw86225_haptic_set_wav_seq(aw86225, i, + aw86225->pattern[budry].patternid[i] + 1); + aw86225_haptic_set_wav_loop(aw86225, i, + aw86225->pattern[budry].waveloop[i]); + } + + iinfo("main_loop = %d\n", aw86225->pattern[budry].mainloop); + aw86225_haptic_set_main_loop(aw86225, + aw86225->pattern[budry].mainloop); + aw86225_haptic_set_pwm(aw86225, AW86225_PWM_12K); + aw86225_haptic_play_mode(aw86225, AW86225_HAPTIC_RAM_LOOP_MODE); + aw86225_haptic_effect_strength(aw86225); + aw86225_haptic_set_gain(aw86225, aw86225->level); + aw86225_haptic_start(aw86225); + } } iinfo("%s: exit\n", __func__); @@ -1969,6 +2021,23 @@ static void aw86225_long_vibrate_work_routine(FAR void *arg) wd_start(&aw86225->timer, MSEC2TICK(aw86225->duration), aw86225_vibrator_timer_func, (wdparm_t)aw86225); } + else if (aw86225->activate_mode == AW86225_HAPTIC_ACTIVATE_RTP_MODE) + { + int budry = aw86225->effect_id - + aw86225->config->effect_id_boundary; + iinfo("activate_mode(AW86225_HAPTIC_ACTIVATE_RTP_MODE) = %d\n", + aw86225->activate_mode); + aw86225_haptic_ram_vbat_compensate(aw86225, true); + aw86225_haptic_play_effect_seq(aw86225, true); + + /* run ms timer */ + + iinfo("pattern duration = %d", aw86225->pattern[budry].duration); + wd_start(&aw86225->timer, + MSEC2TICK(aw86225->pattern[budry].duration), + aw86225_vibrator_timer_func, (wdparm_t)aw86225); + aw86225->wk_lock_flag = 1; + } else { ierr("%s: activate_mode error\n", __func__); @@ -2150,11 +2219,18 @@ static int aw86225_haptics_upload_effect(FAR struct ff_lowerhalf_s *lower, __func__, aw86225->effect_id, aw86225->activate_mode); int budry = aw86225->effect_id - aw86225->config->effect_id_boundary; +#ifdef CONFIG_AW86225_RTP_FILE_SUPPORT data[1] = aw86225->config->rtp_time[budry] / 1000; data[2] = aw86225->config->rtp_time[budry] % 1000; iinfo("%s: data[1] = %d data[2] = %d, rtp_time %d\n", __func__, data[1], data[2], aw86225->config->rtp_time[budry]); +#else + data[1] = 0; + data[2] = aw86225->pattern[budry].duration; + iinfo("data[2] = %d, waveloop time = %d\n", data[2], + aw86225->pattern[budry].duration); +#endif } memcpy(effect->u.periodic.custom_data, data, sizeof(int16_t) * 3); @@ -2207,12 +2283,17 @@ static int aw86225_haptics_playback(struct ff_lowerhalf_s *lower, aw86225->activate_mode == AW86225_HAPTIC_ACTIVATE_RTP_MODE) { iinfo("%s: enter rtp_mode\n", __func__); +#ifdef CONFIG_AW86225_RTP_FILE_SUPPORT work_queue(HPWORK, &aw86225->rtp_work, aw86225_rtp_work_routine, aw86225, 0); if (val == 0) { atomic_store(&aw86225->exit_in_rtp_loop, 1); } +#else + work_queue(HPWORK, &aw86225->long_vibrate_work, + aw86225_long_vibrate_work_routine, aw86225, 0); +#endif } return OK; @@ -2329,6 +2410,7 @@ int aw86225_initialize(FAR struct i2c_master_s *master, aw86225->effects_count = config->effects_count; aw86225->is_used_irq = config->is_used_irq; aw86225->predefined = config->predefined; + aw86225->pattern = config->pattern; aw86225->config = config->config; aw86225->irq = config->irq; aw86225->i2c = master; diff --git a/drivers/input/aw86225_internal.h b/drivers/input/aw86225_internal.h index 7b52d8e7fcf..1dda28f1799 100644 --- a/drivers/input/aw86225_internal.h +++ b/drivers/input/aw86225_internal.h @@ -227,6 +227,7 @@ struct aw86225 struct work_s ram_work; struct aw86225_hap_config hap_config; struct aw86225_hap_play_info play; + FAR struct aw86225_pattern_s *pattern; FAR struct aw86225_hap_effect *predefined; struct aw86225_hap_effect constant; FAR struct aw86225_config *config; diff --git a/include/nuttx/input/aw86225.h b/include/nuttx/input/aw86225.h index 57fcca39d9a..655b8f9f7da 100644 --- a/include/nuttx/input/aw86225.h +++ b/include/nuttx/input/aw86225.h @@ -43,6 +43,18 @@ * Public Types ****************************************************************************/ +/* struct aw86225_pattern_s - effect pattern configuration parameters + */ + +struct aw86225_pattern_s +{ + uint8_t patternid[8]; + uint8_t waveloop[8]; + uint8_t mainloop; + float strength; + uint32_t duration; /* in millisecond */ +}; + /* struct aw86225_hap_effect - effect configuration parameters */ @@ -129,6 +141,7 @@ struct aw86225_board_config uint8_t addr; /* I2C address */ int freq; /* I2C frequency */ FAR struct aw86225_hap_effect *predefined; + FAR struct aw86225_pattern_s *pattern; /* Motor driver registration path */