Dim the haptic duration a bit.

This commit is contained in:
Thomas Göttgens
2026-05-19 12:37:25 +02:00
parent c7c7e628c5
commit 8a82f5317b
3 changed files with 39 additions and 42 deletions
+31 -20
View File
@@ -35,9 +35,9 @@ void HapticFeedback::pulse(uint16_t durationMs)
{
motorWrite(true);
pulseOffAt = millis() + durationMs;
if (pulseOffAt == 0) // disambiguate from "no pulse active" sentinel on millis() wrap
if (pulseOffAt == 0) // 0 is the "no pulse" sentinel
pulseOffAt = 1;
setIntervalFromNow(durationMs);
scheduleNext();
}
void HapticFeedback::armDelayedPulse(uint16_t delayMs, uint16_t durationMs)
@@ -46,7 +46,7 @@ void HapticFeedback::armDelayedPulse(uint16_t delayMs, uint16_t durationMs)
if (delayedPulseAt == 0)
delayedPulseAt = 1;
delayedPulseDuration = durationMs;
setIntervalFromNow(delayMs);
scheduleNext();
}
void HapticFeedback::cancelDelayedPulse()
@@ -54,31 +54,42 @@ void HapticFeedback::cancelDelayedPulse()
delayedPulseAt = 0;
}
int32_t HapticFeedback::runOnce()
void HapticFeedback::scheduleNext()
{
uint32_t now = millis();
// End an in-flight pulse if its time has come.
if (pulseOffAt != 0 && (int32_t)(now - pulseOffAt) >= 0) {
motorWrite(false);
pulseOffAt = 0;
}
// Fire an armed delayed pulse if its time has come.
if (delayedPulseAt != 0 && (int32_t)(now - delayedPulseAt) >= 0) {
uint16_t dur = delayedPulseDuration;
delayedPulseAt = 0;
pulse(dur);
}
// Sleep until the next scheduled event, or idle long if nothing pending.
uint32_t next = 0;
if (pulseOffAt != 0)
next = pulseOffAt;
if (delayedPulseAt != 0 && (next == 0 || (int32_t)(delayedPulseAt - next) < 0))
next = delayedPulseAt;
if (next == 0)
return 60 * 1000; // nothing pending — idle for a minute
return;
int32_t delay = (int32_t)(next - now);
setIntervalFromNow(delay > 0 ? (unsigned long)delay : 0);
}
int32_t HapticFeedback::runOnce()
{
uint32_t now = millis();
if (pulseOffAt != 0 && (int32_t)(now - pulseOffAt) >= 0) {
motorWrite(false);
pulseOffAt = 0;
}
if (delayedPulseAt != 0 && (int32_t)(now - delayedPulseAt) >= 0) {
uint16_t dur = delayedPulseDuration;
delayedPulseAt = 0;
pulse(dur);
}
uint32_t next = 0;
if (pulseOffAt != 0)
next = pulseOffAt;
if (delayedPulseAt != 0 && (next == 0 || (int32_t)(delayedPulseAt - next) < 0))
next = delayedPulseAt;
if (next == 0)
return 60 * 1000;
int32_t delay = (int32_t)(next - now);
return delay > 0 ? delay : 0;
}
+5 -17
View File
@@ -7,41 +7,29 @@
#include "concurrency/OSThread.h"
#include <stdint.h>
// Drives short, non-blocking pulses on a GPIO-controlled vibration motor.
// A variant opts in by defining HAPTIC_FEEDBACK_PIN; HAPTIC_FEEDBACK_ACTIVE_LOW
// inverts the drive polarity (default: active-high — pin HIGH = motor on).
//
// Used by the touch button to produce button-like haptic feedback. Coexists
// with ExternalNotificationModule if both target the same pin — pulses are
// fire-and-forget, no synchronization, last writer wins.
// Non-blocking pulses on a GPIO vibration motor. HAPTIC_FEEDBACK_ACTIVE_LOW inverts polarity.
class HapticFeedback : public concurrency::OSThread
{
public:
HapticFeedback();
// Turn motor on now, schedule off after durationMs.
void pulse(uint16_t durationMs = 30);
// Schedule a one-shot pulse to fire delayMs from now.
void armDelayedPulse(uint16_t delayMs, uint16_t durationMs = 30);
// Cancel a previously-armed delayed pulse (no effect if none pending).
void cancelDelayedPulse();
protected:
int32_t runOnce() override;
private:
uint32_t pulseOffAt = 0; // millis() when current pulse should end (0 = no pulse active)
uint32_t delayedPulseAt = 0; // millis() when armed pulse should fire (0 = nothing armed)
uint32_t pulseOffAt = 0;
uint32_t delayedPulseAt = 0;
uint16_t delayedPulseDuration = 0;
void motorWrite(bool on);
// Reschedule to the soonest pending event so later arms don't clobber earlier wakes.
void scheduleNext();
};
extern HapticFeedback *hapticFeedback;
// Lazy-instantiate the global on first call. Safe to call repeatedly.
void initHapticFeedback();
#endif // HAPTIC_FEEDBACK_PIN
+3 -5
View File
@@ -240,14 +240,12 @@ void InputBroker::Init()
};
#endif
#if defined(HAPTIC_FEEDBACK_PIN)
// Haptic feedback: short pulse on touch contact, and a second short
// pulse when the long-press fires (BACK). The delayed pulse delay
// matches touchConfig.longPressTime's default (500 ms).
// Blip on touch, second blip when long-press fires (500 ms = touchConfig.longPressTime default).
touchConfig.suppressLeadUpSound = true;
initHapticFeedback();
touchConfig.onPress = []() {
hapticFeedback->pulse(30);
hapticFeedback->armDelayedPulse(500, 30);
hapticFeedback->pulse(80);
hapticFeedback->armDelayedPulse(500, 80);
};
touchConfig.onRelease = []() { hapticFeedback->cancelDelayedPulse(); };
#endif