1
0
Fork 0
forked from nuttx/nuttx-update

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 <fangpeina@xiaomi.com>
This commit is contained in:
fangpeina 2024-10-11 22:38:55 +08:00 committed by Xiang Xiao
parent ea20ae588a
commit a719db1b58
4 changed files with 136 additions and 31 deletions

View file

@ -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

View file

@ -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, &reg_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, &reg_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;

View file

@ -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;

View file

@ -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 */