1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-06-09 09:38:46 +00:00

feat(core): improve loader haptic effect

[no changelog]
This commit is contained in:
cepetr 2024-04-29 10:37:00 +02:00 committed by TychoVrahe
parent 2e58a4959f
commit 04d5017228
5 changed files with 47 additions and 18 deletions

View File

@ -358,7 +358,8 @@ fn generate_trezorhal_bindings() {
.allowlist_function("button_read") .allowlist_function("button_read")
// haptic // haptic
.allowlist_type("haptic_effect_t") .allowlist_type("haptic_effect_t")
.allowlist_function("haptic_play"); .allowlist_function("haptic_play")
.allowlist_function("haptic_play_rtp");
// Write the bindings to a file in the OUR_DIR. // Write the bindings to a file in the OUR_DIR.
bindings bindings

View File

@ -11,3 +11,9 @@ pub fn play(effect: HapticEffect) {
ffi::haptic_play(effect as _); ffi::haptic_play(effect as _);
} }
} }
pub fn play_rtp(amplitude: i8, duration: u16) {
unsafe {
ffi::haptic_play_rtp(amplitude, duration);
}
}

View File

@ -1,5 +1,5 @@
#[cfg(feature = "haptic")] #[cfg(feature = "haptic")]
use crate::trezorhal::haptic::{play, HapticEffect}; use crate::trezorhal::haptic::{self, play, HapticEffect};
use crate::{ use crate::{
time::{Duration, Instant}, time::{Duration, Instant},
ui::{ ui::{
@ -7,6 +7,7 @@ use crate::{
component::{Component, Event, EventCtx, Pad}, component::{Component, Event, EventCtx, Pad},
display::{self, toif::Icon, Color}, display::{self, toif::Icon, Color},
geometry::{Offset, Rect}, geometry::{Offset, Rect},
lerp::Lerp,
model_tt::constant, model_tt::constant,
util::animation_disabled, util::animation_disabled,
}, },
@ -173,6 +174,10 @@ impl Component for Loader {
} else if self.is_completely_shrunk(now) { } else if self.is_completely_shrunk(now) {
return Some(LoaderMsg::ShrunkCompletely); return Some(LoaderMsg::ShrunkCompletely);
} else { } else {
let progress = self.progress(now).unwrap() as f32 / 1000.0;
let ampl = i16::lerp(0, 76, progress);
haptic::play_rtp(ampl as i8, 100);
// There is further progress in the animation, request an animation frame event. // There is further progress in the animation, request an animation frame event.
ctx.request_anim_frame(); ctx.request_anim_frame();
} }

View File

@ -23,4 +23,11 @@ bool haptic_test(uint16_t duration_ms);
// Play haptic effect // Play haptic effect
void haptic_play(haptic_effect_t effect); void haptic_play(haptic_effect_t effect);
// Starts the haptic motor with a specified amplitude and period
//
// The function can be invoked repeatedly during the specified duration
// (`duration_ms`) to modify the amplitude dynamically, allowing
// the creation of customized haptic effects.
bool haptic_play_rtp(int8_t amplitude, uint16_t duration_ms);
#endif #endif

View File

@ -94,6 +94,11 @@ void haptic_calibrate(void) {
HAL_Delay(3000); HAL_Delay(3000);
} }
// Set to `true` if real-time playing is activated. to
// This prevents the repeated set of `DRV2625_REG_MODE` register
// which would otherwise stop all playback.
static bool playing_rtp = false;
void haptic_init(void) { void haptic_init(void) {
// select library // select library
set_reg(DRV2625_REG_LIBRARY, LIB_SEL | DRV2625_REG_LIBRARY_GAIN_25); set_reg(DRV2625_REG_LIBRARY, LIB_SEL | DRV2625_REG_LIBRARY_GAIN_25);
@ -124,28 +129,31 @@ void haptic_init(void) {
TIM_Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; TIM_Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
TIM_Handle.Init.CounterMode = TIM_COUNTERMODE_UP; TIM_Handle.Init.CounterMode = TIM_COUNTERMODE_UP;
TIM_Handle.Init.RepetitionCounter = 0; TIM_Handle.Init.RepetitionCounter = 0;
HAL_TIM_PWM_Init(&TIM_Handle); HAL_TIM_OnePulse_Init(&TIM_Handle, TIM_OPMODE_SINGLE);
TIM_OC_InitTypeDef TIM_OC_InitStructure = {0}; TIM_OnePulse_InitTypeDef TIM_OP_InitStructure = {0};
TIM_OC_InitStructure.OCMode = TIM_OCMODE_PWM2; TIM_OP_InitStructure.OCMode = TIM_OCMODE_PWM2;
TIM_OC_InitStructure.OCPolarity = TIM_OCPOLARITY_HIGH; TIM_OP_InitStructure.OCPolarity = TIM_OCPOLARITY_HIGH;
TIM_OC_InitStructure.Pulse = 1; TIM_OP_InitStructure.Pulse = 1;
TIM_OC_InitStructure.OCNPolarity = TIM_OCNPOLARITY_HIGH; TIM_OP_InitStructure.OCNPolarity = TIM_OCNPOLARITY_HIGH;
TIM_OC_InitStructure.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_OnePulse_ConfigChannel(&TIM_Handle, &TIM_OP_InitStructure,
HAL_TIM_PWM_ConfigChannel(&TIM_Handle, &TIM_OC_InitStructure, TIM_CHANNEL_1); TIM_CHANNEL_1, TIM_CHANNEL_2);
HAL_TIM_OC_Start(&TIM_Handle, TIM_CHANNEL_1); HAL_TIM_OC_Start(&TIM_Handle, TIM_CHANNEL_1);
TIM16->CR1 |= TIM_CR1_OPM;
TIM16->BDTR |= TIM_BDTR_MOE; TIM16->BDTR |= TIM_BDTR_MOE;
} }
static bool haptic_play_RTP(int8_t amplitude, uint16_t duration_ms) { bool haptic_play_rtp(int8_t amplitude, uint16_t duration_ms) {
if (!playing_rtp) {
if (!set_reg(DRV2625_REG_MODE, if (!set_reg(DRV2625_REG_MODE,
DRV2625_REG_MODE_RTP | DRV2625_REG_MODE_TRGFUNC_ENABLE)) { DRV2625_REG_MODE_RTP | DRV2625_REG_MODE_TRGFUNC_ENABLE)) {
return false; return false;
} }
playing_rtp = true;
}
if (!set_reg(DRV2625_REG_RTP, (uint8_t)amplitude)) { if (!set_reg(DRV2625_REG_RTP, (uint8_t)amplitude)) {
return false; return false;
} }
@ -166,6 +174,8 @@ static bool haptic_play_RTP(int8_t amplitude, uint16_t duration_ms) {
} }
static void haptic_play_lib(drv2625_lib_effect_t effect) { static void haptic_play_lib(drv2625_lib_effect_t effect) {
playing_rtp = false;
set_reg(DRV2625_REG_MODE, DRV2625_REG_MODE_WAVEFORM); set_reg(DRV2625_REG_MODE, DRV2625_REG_MODE_WAVEFORM);
set_reg(DRV2625_REG_WAVESEQ1, effect); set_reg(DRV2625_REG_WAVESEQ1, effect);
set_reg(DRV2625_REG_WAVESEQ2, 0); set_reg(DRV2625_REG_WAVESEQ2, 0);
@ -175,13 +185,13 @@ static void haptic_play_lib(drv2625_lib_effect_t effect) {
void haptic_play(haptic_effect_t effect) { void haptic_play(haptic_effect_t effect) {
switch (effect) { switch (effect) {
case HAPTIC_BUTTON_PRESS: case HAPTIC_BUTTON_PRESS:
haptic_play_RTP(PRESS_EFFECT_AMPLITUDE, PRESS_EFFECT_DURATION); haptic_play_rtp(PRESS_EFFECT_AMPLITUDE, PRESS_EFFECT_DURATION);
break; break;
case HAPTIC_ALERT: case HAPTIC_ALERT:
haptic_play_lib(ALERT_750MS_100); haptic_play_lib(ALERT_750MS_100);
break; break;
case HAPTIC_HOLD_TO_CONFIRM: case HAPTIC_HOLD_TO_CONFIRM:
haptic_play_lib(TRANSITION_RAMP_UP_SHORT_SMOOTH_1); haptic_play_lib(DOUBLE_CLICK_60);
break; break;
default: default:
break; break;
@ -189,5 +199,5 @@ void haptic_play(haptic_effect_t effect) {
} }
bool haptic_test(uint16_t duration_ms) { bool haptic_test(uint16_t duration_ms) {
return haptic_play_RTP(PRODTEST_EFFECT_AMPLITUDE, duration_ms); return haptic_play_rtp(PRODTEST_EFFECT_AMPLITUDE, duration_ms);
} }