rawinput: custom threshold for BAT (button-analog type) (#654)

## Link to GitHub Issue or related Pull Request, if one exists
#653 

## Description of change
By default, BAT Positive / Negative binds trigger when the stick is
tilted 10% off the center.

This needs a bit more customization since:

1. User may want to customize the center point (e.g., guitar controller
neutral position)
2. User may want to adjust the sensitivity (e.g., guitar controller tilt
angle to trigger wailing).

## Testing
WIP
This commit is contained in:
bicarus
2026-04-22 01:14:15 -07:00
committed by GitHub
parent 1147ed9858
commit f2dca0265f
6 changed files with 92 additions and 3 deletions
+12 -2
View File
@@ -199,9 +199,19 @@ GameAPI::Buttons::State GameAPI::Buttons::getState(rawinput::RawInputManager *ma
if (vKey < value_states->size()) { if (vKey < value_states->size()) {
auto value = value_states->at(vKey); auto value = value_states->at(vKey);
if (current_button->getAnalogType() == BAT_POSITIVE) { if (current_button->getAnalogType() == BAT_POSITIVE) {
state = value > 0.6f ? BUTTON_PRESSED : BUTTON_NOT_PRESSED; float threshold = 0.6f;
if (current_button->getBatThreshold() > 0) {
threshold = std::clamp(current_button->getBatThreshold() / 100.f, 0.01f, 0.99f);
}
state = value > threshold ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
} else if (current_button->getAnalogType() == BAT_NEGATIVE) { } else if (current_button->getAnalogType() == BAT_NEGATIVE) {
state = value < 0.4f ? BUTTON_PRESSED : BUTTON_NOT_PRESSED; float threshold = 0.4f;
if (current_button->getBatThreshold() > 0) {
threshold = std::clamp((100 - current_button->getBatThreshold()) / 100.f, 0.01f, 0.99f);
}
state = value < threshold ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
} else { } else {
state = value > 0.01f ? BUTTON_PRESSED : BUTTON_NOT_PRESSED; state = value > 0.01f ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
} }
+10
View File
@@ -56,6 +56,7 @@ private:
ButtonAnalogType analog_type = BAT_NONE; ButtonAnalogType analog_type = BAT_NONE;
double debounce_up = 0.0; double debounce_up = 0.0;
double debounce_down = 0.0; double debounce_down = 0.0;
int bat_threshold = 0; // for positive/negative only, value in percentage, zero is default
bool invert = false; bool invert = false;
bool is_temporary = false; bool is_temporary = false;
@@ -109,6 +110,7 @@ public:
alternatives.clear(); alternatives.clear();
device_identifier = ""; device_identifier = "";
analog_type = BAT_NONE; analog_type = BAT_NONE;
bat_threshold = 0;
} }
std::string getDisplayString(rawinput::RawInputManager* manager); std::string getDisplayString(rawinput::RawInputManager* manager);
@@ -169,6 +171,14 @@ public:
this->debounce_down = debounce_time_down; this->debounce_down = debounce_time_down;
} }
inline void setBatThreshold(int bat_threshold) {
this->bat_threshold = bat_threshold;
}
inline int getBatThreshold() const {
return this->bat_threshold;
}
inline bool getInvert() const { inline bool getInvert() const {
return this->invert; return this->invert;
} }
+12
View File
@@ -162,6 +162,7 @@ bool Config::addGame(Game &game) {
auto analogType = (int) BAT_NONE; auto analogType = (int) BAT_NONE;
double debounce_up = 0.0; double debounce_up = 0.0;
double debounce_down = 0.0; double debounce_down = 0.0;
int bat_threshold = 0;
int velocity_threshold = 0; int velocity_threshold = 0;
bool invert = false; bool invert = false;
tinyxml2::XMLError attrError = gameButtonNode->QueryIntAttribute("vkey", &vKey); tinyxml2::XMLError attrError = gameButtonNode->QueryIntAttribute("vkey", &vKey);
@@ -169,6 +170,7 @@ bool Config::addGame(Game &game) {
gameButtonNode->QueryIntAttribute("analogtype", &analogType); gameButtonNode->QueryIntAttribute("analogtype", &analogType);
gameButtonNode->QueryDoubleAttribute("debounce_up", &debounce_up); gameButtonNode->QueryDoubleAttribute("debounce_up", &debounce_up);
gameButtonNode->QueryDoubleAttribute("debounce_down", &debounce_down); gameButtonNode->QueryDoubleAttribute("debounce_down", &debounce_down);
gameButtonNode->QueryIntAttribute("bat_threshold", &bat_threshold);
gameButtonNode->QueryIntAttribute("velocity_threshold", &velocity_threshold); gameButtonNode->QueryIntAttribute("velocity_threshold", &velocity_threshold);
gameButtonNode->QueryBoolAttribute("invert", &invert); gameButtonNode->QueryBoolAttribute("invert", &invert);
if (attrError != tinyxml2::XMLError::XML_SUCCESS) { if (attrError != tinyxml2::XMLError::XML_SUCCESS) {
@@ -180,6 +182,7 @@ bool Config::addGame(Game &game) {
gameButtonNode->SetAttribute("devid", button->getDeviceIdentifier().c_str()); gameButtonNode->SetAttribute("devid", button->getDeviceIdentifier().c_str());
gameButtonNode->SetAttribute("debounce_up", debounce_up); gameButtonNode->SetAttribute("debounce_up", debounce_up);
gameButtonNode->SetAttribute("debounce_down", debounce_down); gameButtonNode->SetAttribute("debounce_down", debounce_down);
gameButtonNode->SetAttribute("bat_threshold", bat_threshold);
gameButtonNode->SetAttribute("velocity_threshold", velocity_threshold); gameButtonNode->SetAttribute("velocity_threshold", velocity_threshold);
gameButtonNode->SetAttribute("invert", invert); gameButtonNode->SetAttribute("invert", invert);
gameButtonsNode->InsertEndChild(gameButtonNode); gameButtonsNode->InsertEndChild(gameButtonNode);
@@ -188,6 +191,7 @@ bool Config::addGame(Game &game) {
button->setAnalogType((ButtonAnalogType) analogType); button->setAnalogType((ButtonAnalogType) analogType);
button->setDebounceUp(debounce_up); button->setDebounceUp(debounce_up);
button->setDebounceDown(debounce_down); button->setDebounceDown(debounce_down);
button->setBatThreshold(bat_threshold);
button->setVelocityThreshold(velocity_threshold); button->setVelocityThreshold(velocity_threshold);
button->setInvert(invert); button->setInvert(invert);
if (devid) { if (devid) {
@@ -207,6 +211,7 @@ bool Config::addGame(Game &game) {
gameButtonNode->SetAttribute("analogtype", (int) it.getAnalogType()); gameButtonNode->SetAttribute("analogtype", (int) it.getAnalogType());
gameButtonNode->SetAttribute("debounce_up", it.getDebounceUp()); gameButtonNode->SetAttribute("debounce_up", it.getDebounceUp());
gameButtonNode->SetAttribute("debounce_down", it.getDebounceDown()); gameButtonNode->SetAttribute("debounce_down", it.getDebounceDown());
gameButtonNode->SetAttribute("bat_threshold", it.getBatThreshold());
gameButtonNode->SetAttribute("velocity_threshold", it.getVelocityThreshold()); gameButtonNode->SetAttribute("velocity_threshold", it.getVelocityThreshold());
gameButtonNode->SetAttribute("invert", it.getInvert()); gameButtonNode->SetAttribute("invert", it.getInvert());
gameButtonNode->SetAttribute("devid", it.getDeviceIdentifier().c_str()); gameButtonNode->SetAttribute("devid", it.getDeviceIdentifier().c_str());
@@ -432,6 +437,7 @@ bool Config::addGame(Game &game) {
gameButtonNode->SetAttribute("analogtype", it.getAnalogType()); gameButtonNode->SetAttribute("analogtype", it.getAnalogType());
gameButtonNode->SetAttribute("debounce_up", it.getDebounceUp()); gameButtonNode->SetAttribute("debounce_up", it.getDebounceUp());
gameButtonNode->SetAttribute("debounce_down", it.getDebounceDown()); gameButtonNode->SetAttribute("debounce_down", it.getDebounceDown());
gameButtonNode->SetAttribute("bat_threshold", it.getBatThreshold());
gameButtonNode->SetAttribute("velocity_threshold", it.getVelocityThreshold()); gameButtonNode->SetAttribute("velocity_threshold", it.getVelocityThreshold());
gameButtonNode->SetAttribute("invert", it.getInvert()); gameButtonNode->SetAttribute("invert", it.getInvert());
gameButtonNode->SetAttribute("devid", it.getDeviceIdentifier().c_str()); gameButtonNode->SetAttribute("devid", it.getDeviceIdentifier().c_str());
@@ -535,6 +541,7 @@ bool Config::updateBinding(const Game &game, const Button &button, int alternati
gameButtonNode->SetAttribute("analogtype", (int) button.getAnalogType()); gameButtonNode->SetAttribute("analogtype", (int) button.getAnalogType());
gameButtonNode->SetAttribute("debounce_up", button.getDebounceUp()); gameButtonNode->SetAttribute("debounce_up", button.getDebounceUp());
gameButtonNode->SetAttribute("debounce_down", button.getDebounceDown()); gameButtonNode->SetAttribute("debounce_down", button.getDebounceDown());
gameButtonNode->SetAttribute("bat_threshold", button.getBatThreshold());
gameButtonNode->SetAttribute("velocity_threshold", button.getVelocityThreshold()); gameButtonNode->SetAttribute("velocity_threshold", button.getVelocityThreshold());
gameButtonNode->SetAttribute("invert", button.getInvert()); gameButtonNode->SetAttribute("invert", button.getInvert());
gameButtonNode->SetAttribute("devid", button.getDeviceIdentifier().c_str()); gameButtonNode->SetAttribute("devid", button.getDeviceIdentifier().c_str());
@@ -551,6 +558,7 @@ bool Config::updateBinding(const Game &game, const Button &button, int alternati
gameButtonNode->SetAttribute("analogtype", 0); gameButtonNode->SetAttribute("analogtype", 0);
gameButtonNode->SetAttribute("debounce_up", 0.0); gameButtonNode->SetAttribute("debounce_up", 0.0);
gameButtonNode->SetAttribute("debounce_down", 0.0); gameButtonNode->SetAttribute("debounce_down", 0.0);
gameButtonNode->SetAttribute("bat_threshold", 0);
gameButtonNode->SetAttribute("velocity_threshold", 0); gameButtonNode->SetAttribute("velocity_threshold", 0);
gameButtonNode->SetAttribute("invert", false); gameButtonNode->SetAttribute("invert", false);
gameButtonNode->SetAttribute("devid", ""); gameButtonNode->SetAttribute("devid", "");
@@ -946,12 +954,14 @@ std::vector<Button> Config::getButtons(const std::string &gameName) {
auto analogType = (int) BAT_NONE; auto analogType = (int) BAT_NONE;
double debounce_up = 0.0; double debounce_up = 0.0;
double debounce_down = 0.0; double debounce_down = 0.0;
int bat_threshold = 0;
int velocity_threshold = 0; int velocity_threshold = 0;
bool invert = false; bool invert = false;
gameButtonNode->QueryIntAttribute("vkey", &vKey); gameButtonNode->QueryIntAttribute("vkey", &vKey);
gameButtonNode->QueryIntAttribute("analogtype", &analogType); gameButtonNode->QueryIntAttribute("analogtype", &analogType);
gameButtonNode->QueryDoubleAttribute("debounce_up", &debounce_up); gameButtonNode->QueryDoubleAttribute("debounce_up", &debounce_up);
gameButtonNode->QueryDoubleAttribute("debounce_down", &debounce_down); gameButtonNode->QueryDoubleAttribute("debounce_down", &debounce_down);
gameButtonNode->QueryIntAttribute("bat_threshold", &bat_threshold);
gameButtonNode->QueryIntAttribute("velocity_threshold", &velocity_threshold); gameButtonNode->QueryIntAttribute("velocity_threshold", &velocity_threshold);
gameButtonNode->QueryBoolAttribute("invert", &invert); gameButtonNode->QueryBoolAttribute("invert", &invert);
const char *devid = gameButtonNode->Attribute("devid"); const char *devid = gameButtonNode->Attribute("devid");
@@ -966,6 +976,7 @@ std::vector<Button> Config::getButtons(const std::string &gameName) {
alt.setAnalogType((ButtonAnalogType) analogType); alt.setAnalogType((ButtonAnalogType) analogType);
alt.setDebounceUp(debounce_up); alt.setDebounceUp(debounce_up);
alt.setDebounceDown(debounce_down); alt.setDebounceDown(debounce_down);
alt.setBatThreshold(bat_threshold);
alt.setVelocityThreshold(velocity_threshold); alt.setVelocityThreshold(velocity_threshold);
alt.setInvert(invert); alt.setInvert(invert);
if (devid) { if (devid) {
@@ -984,6 +995,7 @@ std::vector<Button> Config::getButtons(const std::string &gameName) {
button.setAnalogType((ButtonAnalogType) analogType); button.setAnalogType((ButtonAnalogType) analogType);
button.setDebounceUp(debounce_up); button.setDebounceUp(debounce_up);
button.setDebounceDown(debounce_down); button.setDebounceDown(debounce_down);
button.setBatThreshold(bat_threshold);
button.setVelocityThreshold(velocity_threshold); button.setVelocityThreshold(velocity_threshold);
button.setInvert(invert); button.setInvert(invert);
if (devid) { if (devid) {
+5
View File
@@ -24,6 +24,7 @@ namespace overlay::windows {
el->SetAttribute("invert", entry.invert); el->SetAttribute("invert", entry.invert);
el->SetAttribute("debounce_up", entry.debounce_up); el->SetAttribute("debounce_up", entry.debounce_up);
el->SetAttribute("debounce_down", entry.debounce_down); el->SetAttribute("debounce_down", entry.debounce_down);
el->SetAttribute("bat_threshold", entry.bat_threshold);
el->SetAttribute("velocity_threshold", entry.velocity_threshold); el->SetAttribute("velocity_threshold", entry.velocity_threshold);
parent->InsertEndChild(el); parent->InsertEndChild(el);
} }
@@ -49,6 +50,10 @@ namespace overlay::windows {
el->QueryIntAttribute("velocity_threshold", &vel); el->QueryIntAttribute("velocity_threshold", &vel);
entry.velocity_threshold = (unsigned short)vel; entry.velocity_threshold = (unsigned short)vel;
int bat = 0;
el->QueryIntAttribute("bat_threshold", &bat);
entry.bat_threshold = bat;
return entry; return entry;
} }
+51 -1
View File
@@ -1063,6 +1063,7 @@ namespace overlay::windows {
button->setAnalogType(BAT_NONE); button->setAnalogType(BAT_NONE);
button->setDebounceUp(0.0); button->setDebounceUp(0.0);
button->setDebounceDown(0.0); button->setDebounceDown(0.0);
button->setBatThreshold(0);
button->setVelocityThreshold(0); button->setVelocityThreshold(0);
button->setInvert(false); button->setInvert(false);
button->setLastState(GameAPI::Buttons::BUTTON_NOT_PRESSED); button->setLastState(GameAPI::Buttons::BUTTON_NOT_PRESSED);
@@ -1265,6 +1266,7 @@ namespace overlay::windows {
button->setAnalogType(bat); button->setAnalogType(bat);
button->setDebounceUp(0.0); button->setDebounceUp(0.0);
button->setDebounceDown(0.0); button->setDebounceDown(0.0);
button->setBatThreshold(0);
button->setVelocityThreshold(0); button->setVelocityThreshold(0);
::Config::getInstance().updateBinding( ::Config::getInstance().updateBinding(
games_list[games_selected], *button, games_list[games_selected], *button,
@@ -1313,6 +1315,7 @@ namespace overlay::windows {
button->setAnalogType(buffer[0]); button->setAnalogType(buffer[0]);
button->setDebounceUp(0.0); button->setDebounceUp(0.0);
button->setDebounceDown(0.0); button->setDebounceDown(0.0);
button->setBatThreshold(0);
button->setVelocityThreshold(0); button->setVelocityThreshold(0);
::Config::getInstance().updateBinding( ::Config::getInstance().updateBinding(
games_list[games_selected], *button, games_list[games_selected], *button,
@@ -1360,6 +1363,7 @@ namespace overlay::windows {
button->setAnalogType(BAT_NONE); button->setAnalogType(BAT_NONE);
button->setDebounceUp(0.0); button->setDebounceUp(0.0);
button->setDebounceDown(0.0); button->setDebounceDown(0.0);
button->setBatThreshold(0);
// same idea as setMidiVKey - keep velocity threshold consistent // same idea as setMidiVKey - keep velocity threshold consistent
button->setVelocityThreshold( button->setVelocityThreshold(
device->midiInfo->v2_velocity_threshold[button->getVKey()]); device->midiInfo->v2_velocity_threshold[button->getVKey()]);
@@ -1385,6 +1389,7 @@ namespace overlay::windows {
button->setAnalogType(BAT_MIDI_CTRL_PRECISION); button->setAnalogType(BAT_MIDI_CTRL_PRECISION);
button->setDebounceUp(0.0); button->setDebounceUp(0.0);
button->setDebounceDown(0.0); button->setDebounceDown(0.0);
button->setBatThreshold(0);
button->setVelocityThreshold(0); button->setVelocityThreshold(0);
::Config::getInstance().updateBinding( ::Config::getInstance().updateBinding(
games_list[games_selected], *button, games_list[games_selected], *button,
@@ -1411,6 +1416,7 @@ namespace overlay::windows {
button->setAnalogType(BAT_MIDI_CTRL_SINGLE); button->setAnalogType(BAT_MIDI_CTRL_SINGLE);
button->setDebounceUp(0.0); button->setDebounceUp(0.0);
button->setDebounceDown(0.0); button->setDebounceDown(0.0);
button->setBatThreshold(0);
button->setVelocityThreshold(0); button->setVelocityThreshold(0);
::Config::getInstance().updateBinding( ::Config::getInstance().updateBinding(
games_list[games_selected], *button, games_list[games_selected], *button,
@@ -1437,6 +1443,7 @@ namespace overlay::windows {
button->setAnalogType(BAT_MIDI_CTRL_ONOFF); button->setAnalogType(BAT_MIDI_CTRL_ONOFF);
button->setDebounceUp(0.0); button->setDebounceUp(0.0);
button->setDebounceDown(0.0); button->setDebounceDown(0.0);
button->setBatThreshold(0);
button->setVelocityThreshold(0); button->setVelocityThreshold(0);
::Config::getInstance().updateBinding( ::Config::getInstance().updateBinding(
games_list[games_selected], *button, games_list[games_selected], *button,
@@ -1462,6 +1469,7 @@ namespace overlay::windows {
button->setAnalogType(BAT_MIDI_PITCH_DOWN); button->setAnalogType(BAT_MIDI_PITCH_DOWN);
button->setDebounceUp(0.0); button->setDebounceUp(0.0);
button->setDebounceDown(0.0); button->setDebounceDown(0.0);
button->setBatThreshold(0);
button->setVelocityThreshold(0); button->setVelocityThreshold(0);
::Config::getInstance().updateBinding( ::Config::getInstance().updateBinding(
games_list[games_selected], *button, games_list[games_selected], *button,
@@ -1482,6 +1490,7 @@ namespace overlay::windows {
button->setAnalogType(BAT_MIDI_PITCH_UP); button->setAnalogType(BAT_MIDI_PITCH_UP);
button->setDebounceUp(0.0); button->setDebounceUp(0.0);
button->setDebounceDown(0.0); button->setDebounceDown(0.0);
button->setBatThreshold(0);
button->setVelocityThreshold(0); button->setVelocityThreshold(0);
::Config::getInstance().updateBinding( ::Config::getInstance().updateBinding(
games_list[games_selected], *button, games_list[games_selected], *button,
@@ -1511,6 +1520,7 @@ namespace overlay::windows {
button->setAnalogType(BAT_NONE); button->setAnalogType(BAT_NONE);
button->setDebounceUp(0.0); button->setDebounceUp(0.0);
button->setDebounceDown(0.0); button->setDebounceDown(0.0);
button->setBatThreshold(0);
button->setVelocityThreshold(0); button->setVelocityThreshold(0);
::Config::getInstance().updateBinding( ::Config::getInstance().updateBinding(
games_list[games_selected], *button, games_list[games_selected], *button,
@@ -1635,6 +1645,7 @@ namespace overlay::windows {
button->setVKey(vKey); button->setVKey(vKey);
button->setDebounceUp(0.0); button->setDebounceUp(0.0);
button->setDebounceDown(0.0); button->setDebounceDown(0.0);
button->setBatThreshold(0);
button->setVelocityThreshold(0); button->setVelocityThreshold(0);
::Config::getInstance().updateBinding( ::Config::getInstance().updateBinding(
games_list[games_selected], *button, games_list[games_selected], *button,
@@ -2050,11 +2061,48 @@ namespace overlay::windows {
// invert // invert
bool invert = button->getInvert(); bool invert = button->getInvert();
if (ImGui::Checkbox("Invert", &invert)) { if (ImGui::Checkbox("Invert Resulting Value", &invert)) {
button->setInvert(invert); button->setInvert(invert);
dirty = true; dirty = true;
} }
// bat threshold
if (device->type == rawinput::HID &&
(button->getAnalogType() == BAT_POSITIVE || button->getAnalogType() == BAT_NEGATIVE)) {
int bat_threshold = button->getBatThreshold();
bool is_active = (bat_threshold > 0);
if (ImGui::Checkbox("Custom Analog Threshold", &is_active)) {
if (!is_active) {
button->setBatThreshold(0);
} else if (bat_threshold == 0) {
button->setBatThreshold(60);
}
dirty = true;
}
ImGui::SameLine();
ImGui::HelpMarker(
"Assuming that 50% is the center, value exceeding 60% triggers the button by default. "
"With this option, you can customize the trigger threshold.\n\n"
"Setting this to 51% means tiny movements will trigger the button (small deadzone), "
"while setting this to 99% means the button will only trigger at maximum value (large deadzone).\n\n"
"Setting this to below 50% adjusts the neutral / center position.");
if (is_active) {
if (ImGui::SliderInt(
"Analog Threshold",
&bat_threshold,
1, 99,
"%d%%",
ImGuiSliderFlags_AlwaysClamp)) {
button->setBatThreshold(bat_threshold);
}
if (ImGui::IsItemDeactivatedAfterEdit()) {
dirty = true;
}
}
}
// state display // state display
ImGui::TextUnformatted(""); ImGui::TextUnformatted("");
if (device != nullptr && device->type == rawinput::MIDI) { if (device != nullptr && device->type == rawinput::MIDI) {
@@ -5283,6 +5331,7 @@ namespace overlay::windows {
btn.setInvert(entry->invert); btn.setInvert(entry->invert);
btn.setDebounceUp(entry->debounce_up); btn.setDebounceUp(entry->debounce_up);
btn.setDebounceDown(entry->debounce_down); btn.setDebounceDown(entry->debounce_down);
btn.setBatThreshold(entry->bat_threshold);
btn.setVelocityThreshold(entry->velocity_threshold); btn.setVelocityThreshold(entry->velocity_threshold);
::Config::getInstance().updateBinding(game, btn, -1); ::Config::getInstance().updateBinding(game, btn, -1);
} else { } else {
@@ -5293,6 +5342,7 @@ namespace overlay::windows {
alt_btn.setInvert(entry->invert); alt_btn.setInvert(entry->invert);
alt_btn.setDebounceUp(entry->debounce_up); alt_btn.setDebounceUp(entry->debounce_up);
alt_btn.setDebounceDown(entry->debounce_down); alt_btn.setDebounceDown(entry->debounce_down);
alt_btn.setBatThreshold(entry->bat_threshold);
alt_btn.setVelocityThreshold(entry->velocity_threshold); alt_btn.setVelocityThreshold(entry->velocity_threshold);
alt_btn.setTemporary(true); alt_btn.setTemporary(true);
btn.getAlternatives().push_back(alt_btn); btn.getAlternatives().push_back(alt_btn);
@@ -17,6 +17,7 @@ namespace overlay::windows {
bool invert = false; bool invert = false;
double debounce_up = 0.0; double debounce_up = 0.0;
double debounce_down = 0.0; double debounce_down = 0.0;
int bat_threshold = 0;
unsigned short velocity_threshold = 0; unsigned short velocity_threshold = 0;
bool is_naive() const { return device_identifier.empty() && vKey != INVALID_VKEY; } bool is_naive() const { return device_identifier.empty() && vKey != INVALID_VKEY; }
@@ -31,6 +32,7 @@ namespace overlay::windows {
e.invert = btn.getInvert(); e.invert = btn.getInvert();
e.debounce_up = btn.getDebounceUp(); e.debounce_up = btn.getDebounceUp();
e.debounce_down = btn.getDebounceDown(); e.debounce_down = btn.getDebounceDown();
e.bat_threshold = btn.getBatThreshold();
e.velocity_threshold = btn.getVelocityThreshold(); e.velocity_threshold = btn.getVelocityThreshold();
return e; return e;
} }