feat(lua): add 'intensity' parameter to playHaptic (#3408)

Co-authored-by: Peter Feerick <peter.feerick@gmail.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
zortrop
2026-08-30 08:57:51 +10:00
committed by GitHub
co-authored by Peter Feerick Claude Sonnet 5
parent f8baae6458
commit 90bbce1763
4 changed files with 102 additions and 9 deletions
+14 -3
View File
@@ -36,6 +36,8 @@ hapticQueue::hapticQueue()
t_queueWidx = 0;
hapticTick = 0;
intensity = userHapticStrength;
}
void hapticQueue::heartbeat()
@@ -46,7 +48,11 @@ void hapticQueue::heartbeat()
if (buzzTimeLeft > 0) {
buzzTimeLeft--; // time gets counted down
#if defined(HAPTIC_PWM)
hapticOn(HAPTIC_STRENGTH() * 20);
if (intensity < userHapticStrength) {
hapticOn(intensity);
} else {
hapticOn(HAPTIC_STRENGTH() * 20);
}
#else
if (hapticTick-- > 0) {
hapticOn();
@@ -65,6 +71,7 @@ void hapticQueue::heartbeat()
else if (t_queueRidx != t_queueWidx) {
buzzTimeLeft = queueHapticLength[t_queueRidx];
buzzPause = queueHapticPause[t_queueRidx];
intensity = queueHapticIntensity[t_queueRidx];
if (!queueHapticRepeat[t_queueRidx]--) {
t_queueRidx = (t_queueRidx + 1) & (HAPTIC_QUEUE_LENGTH-1);
}
@@ -73,13 +80,16 @@ void hapticQueue::heartbeat()
#endif // defined(SIMU)
}
void hapticQueue::play(uint8_t tLen, uint8_t tPause, uint8_t tFlags)
void hapticQueue::play(uint8_t tLen, uint8_t tPause, uint8_t tFlags, uint8_t tIntensity)
{
tLen = getHapticLength(tLen);
if(tLen > 0){
tLen = getHapticLength(tLen);
}
if ((tFlags & PLAY_NOW) || (!busy() && empty())) {
buzzTimeLeft = tLen;
buzzPause = tPause;
intensity = tIntensity;
t_queueWidx = t_queueRidx;
}
else {
@@ -93,6 +103,7 @@ void hapticQueue::play(uint8_t tLen, uint8_t tPause, uint8_t tFlags)
queueHapticLength[t_queueWidx] = tLen;
queueHapticPause[t_queueWidx] = tPause;
queueHapticRepeat[t_queueWidx] = tFlags-1;
queueHapticIntensity[t_queueWidx] = tIntensity;
t_queueWidx = next_queueWidx;
}
}
+11 -3
View File
@@ -23,18 +23,23 @@
#define HAPTIC_QUEUE_LENGTH 4
// sentinel: use HAPTIC_STRENGTH() setting instead of an explicit intensity
constexpr uint8_t userHapticStrength = 255;
class hapticQueue
{
public:
hapticQueue();
// only difference between these two functions is that one does the
// interupt queue (Now) and the other queues for playing ASAP.
void play(uint8_t tLen, uint8_t tPause, uint8_t tRepeat=0);
// The PLAY_NOW flag interrupts and plays immediately; otherwise this
// queues to play as soon as the current buzz finishes.
void play(uint8_t tLen, uint8_t tPause, uint8_t tFlags=0, uint8_t tIntensity=userHapticStrength);
inline bool busy() { return (buzzTimeLeft > 0); }
inline uint8_t getIntensity() { return intensity; }
void event(uint8_t e);
// heartbeat is responsibile for issueing the haptic buzzs and general square waves
@@ -61,10 +66,13 @@ class hapticQueue
uint8_t hapticTick;
uint8_t intensity;
// queue arrays
uint8_t queueHapticLength[HAPTIC_QUEUE_LENGTH];
uint8_t queueHapticPause[HAPTIC_QUEUE_LENGTH];
uint8_t queueHapticRepeat[HAPTIC_QUEUE_LENGTH];
uint8_t queueHapticIntensity[HAPTIC_QUEUE_LENGTH];
};
extern hapticQueue haptic;
+12 -3
View File
@@ -1658,7 +1658,7 @@ static int luaScreenshot(lua_State * L)
}
/*luadoc
@function playHaptic(duration, pause [, flags])
@function playHaptic(duration, pause [, flags [, intensity]])
Generate haptic feedback
@@ -1670,7 +1670,11 @@ Generate haptic feedback
* `0 or not present` play with normal priority
* `PLAY_NOW` play immediately
@status current Introduced in 2.2.0
@param intensity (number) [optional] haptic motor strength, 0-100 (only
effective on boards with PWM-driven haptic support); defaults to the user's
configured haptic strength setting
@status current Introduced in 2.2.0, intensity added in 3.0
*/
static int luaPlayHaptic(lua_State * L)
{
@@ -1678,7 +1682,12 @@ static int luaPlayHaptic(lua_State * L)
int length = luaL_checkinteger(L, 1);
int pause = luaL_checkinteger(L, 2);
int flags = luaL_optinteger(L, 3, 0);
haptic.play(length, pause, flags);
int intensity = luaL_optinteger(L, 4, userHapticStrength);
if (intensity != userHapticStrength) {
if (intensity < 0) intensity = 0;
else if (intensity > 100) intensity = 100;
}
haptic.play(length, pause, flags, intensity);
#else
UNUSED(L);
#endif
+65
View File
@@ -0,0 +1,65 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "gtests.h"
TEST(Haptic, DefaultIntensityUsesUserStrength)
{
hapticQueue hq;
EXPECT_EQ(userHapticStrength, hq.getIntensity());
}
TEST(Haptic, PlayWithoutIntensityKeepsUserStrength)
{
hapticQueue hq;
hq.play(15, 3, PLAY_NOW);
EXPECT_EQ(userHapticStrength, hq.getIntensity());
}
TEST(Haptic, PlayAcceptsCustomIntensityWithCustomDuration)
{
hapticQueue hq;
hq.play(15, 3, PLAY_NOW, 50);
EXPECT_TRUE(hq.busy());
EXPECT_EQ(50, hq.getIntensity());
}
TEST(Haptic, PlayAcceptsMinAndMaxIntensity)
{
hapticQueue hq;
hq.play(15, 3, PLAY_NOW, 0);
EXPECT_EQ(0, hq.getIntensity());
hq.play(15, 3, PLAY_NOW, 100);
EXPECT_EQ(100, hq.getIntensity());
}
TEST(Haptic, QueuedPlayDoesNotChangeCurrentIntensity)
{
hapticQueue hq;
hq.play(15, 3, PLAY_NOW, 50);
ASSERT_TRUE(hq.busy());
ASSERT_EQ(50, hq.getIntensity());
// queue busy -> gets queued rather than applied immediately
hq.play(5, 1, PLAY_REPEAT(1), 80);
EXPECT_EQ(50, hq.getIntensity());
}