mirror of
https://github.com/ravinrabbid/DonCon2040.git
synced 2024-11-20 11:47:07 +01:00
Simplify false hit detection
For now, only allow one input at a time
This commit is contained in:
parent
b17b98068a
commit
092eeb4f07
11
README.md
11
README.md
@ -47,7 +47,8 @@ Few things which you probably want to change more regularly can be changed using
|
|||||||
|
|
||||||
- Controller emulation mode
|
- Controller emulation mode
|
||||||
- LED brightness
|
- LED brightness
|
||||||
- Trigger thresholds and scale level
|
- Trigger thresholds
|
||||||
|
- Hold Time
|
||||||
- Enter BOOTSEL mode for firmware flashing
|
- Enter BOOTSEL mode for firmware flashing
|
||||||
|
|
||||||
Those settings are persisted to flash memory if you choose 'Save' when exiting the Menu and will survive power cycles.
|
Those settings are persisted to flash memory if you choose 'Save' when exiting the Menu and will survive power cycles.
|
||||||
@ -60,14 +61,6 @@ The debounce delay also implicitly serves as the hold time of the input after a
|
|||||||
|
|
||||||
If you notice dropped inputs even if the controller signals a hit on the LED/Display, try to increase this value.
|
If you notice dropped inputs even if the controller signals a hit on the LED/Display, try to increase this value.
|
||||||
|
|
||||||
### Trigger Scale Level
|
|
||||||
|
|
||||||
To avoid false inputs for very hard hits, trigger levels of the non-hit pads are scaled dynamically. The trigger scale level defines how much trigger levels are increased.
|
|
||||||
|
|
||||||
Increase the value if you get false inputs on hard hits, decrease if simultaneous left and right hits are not registered properly.
|
|
||||||
|
|
||||||
Mind that the scaling is non-linear and changes in the higher end of the scale level range have a much larger impact.
|
|
||||||
|
|
||||||
## Hardware
|
## Hardware
|
||||||
|
|
||||||
### IO Board
|
### IO Board
|
||||||
|
@ -44,9 +44,8 @@ const Peripherals::Drum::Config drum_config = {
|
|||||||
80, // Don Right
|
80, // Don Right
|
||||||
50, // Ka Right
|
50, // Ka Right
|
||||||
},
|
},
|
||||||
230, // Trigger threshold scale level
|
|
||||||
|
|
||||||
50, // ADC sample count
|
10, // ADC sample count
|
||||||
25, // Debounce delay in milliseconds
|
25, // Debounce delay in milliseconds
|
||||||
|
|
||||||
true, // Use external ADC
|
true, // Use external ADC
|
||||||
|
@ -32,7 +32,6 @@ class Drum {
|
|||||||
|
|
||||||
AdcInputs adc_inputs;
|
AdcInputs adc_inputs;
|
||||||
Thresholds trigger_thresholds;
|
Thresholds trigger_thresholds;
|
||||||
uint8_t trigger_threshold_scale_level;
|
|
||||||
|
|
||||||
uint8_t sample_count;
|
uint8_t sample_count;
|
||||||
uint16_t debounce_delay_ms;
|
uint16_t debounce_delay_ms;
|
||||||
@ -51,6 +50,7 @@ class Drum {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
enum class Id {
|
enum class Id {
|
||||||
|
NONE,
|
||||||
DON_LEFT,
|
DON_LEFT,
|
||||||
KA_LEFT,
|
KA_LEFT,
|
||||||
DON_RIGHT,
|
DON_RIGHT,
|
||||||
@ -64,11 +64,11 @@ class Drum {
|
|||||||
bool active;
|
bool active;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Pad(uint8_t channel);
|
Pad(const uint8_t channel);
|
||||||
|
|
||||||
uint8_t getChannel() const { return channel; };
|
uint8_t getChannel() const { return channel; };
|
||||||
bool getState() const { return active; };
|
bool getState() const { return active; };
|
||||||
void setState(bool state, uint16_t debounce_delay);
|
void setState(const bool state, const uint16_t debounce_delay);
|
||||||
};
|
};
|
||||||
|
|
||||||
class AdcInterface {
|
class AdcInterface {
|
||||||
@ -105,7 +105,6 @@ class Drum {
|
|||||||
|
|
||||||
void setDebounceDelay(const uint16_t delay);
|
void setDebounceDelay(const uint16_t delay);
|
||||||
void setThresholds(const Config::Thresholds &thresholds);
|
void setThresholds(const Config::Thresholds &thresholds);
|
||||||
void setThresholdScaleLevel(const uint8_t threshold_scale_level);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Doncon::Peripherals
|
} // namespace Doncon::Peripherals
|
||||||
|
@ -23,7 +23,6 @@ class Menu {
|
|||||||
TriggerThresholdDonLeft,
|
TriggerThresholdDonLeft,
|
||||||
TriggerThresholdDonRight,
|
TriggerThresholdDonRight,
|
||||||
TriggerThresholdKaRight,
|
TriggerThresholdKaRight,
|
||||||
TriggerThresholdScaleLevel,
|
|
||||||
DebounceDelay,
|
DebounceDelay,
|
||||||
LedBrightness,
|
LedBrightness,
|
||||||
Reset,
|
Reset,
|
||||||
@ -54,7 +53,6 @@ class Menu {
|
|||||||
GotoPageTriggerThresholdDonLeft,
|
GotoPageTriggerThresholdDonLeft,
|
||||||
GotoPageTriggerThresholdDonRight,
|
GotoPageTriggerThresholdDonRight,
|
||||||
GotoPageTriggerThresholdKaRight,
|
GotoPageTriggerThresholdKaRight,
|
||||||
GotoPageTriggerThresholdScaleLevel,
|
|
||||||
GotoPageDebounceDelay,
|
GotoPageDebounceDelay,
|
||||||
GotoPageLedBrightness,
|
GotoPageLedBrightness,
|
||||||
GotoPageReset,
|
GotoPageReset,
|
||||||
@ -74,7 +72,6 @@ class Menu {
|
|||||||
SetTriggerThresholdDonLeft,
|
SetTriggerThresholdDonLeft,
|
||||||
SetTriggerThresholdDonRight,
|
SetTriggerThresholdDonRight,
|
||||||
SetTriggerThresholdKaRight,
|
SetTriggerThresholdKaRight,
|
||||||
SetTriggerThresholdScaleLevel,
|
|
||||||
SetDebounceDelay,
|
SetDebounceDelay,
|
||||||
SetLedBrightness,
|
SetLedBrightness,
|
||||||
|
|
||||||
|
@ -20,13 +20,11 @@ class SettingsStore {
|
|||||||
uint8_t in_use;
|
uint8_t in_use;
|
||||||
usb_mode_t usb_mode;
|
usb_mode_t usb_mode;
|
||||||
Peripherals::Drum::Config::Thresholds trigger_thresholds;
|
Peripherals::Drum::Config::Thresholds trigger_thresholds;
|
||||||
uint8_t trigger_threshold_scale_level;
|
|
||||||
uint8_t led_brightness;
|
uint8_t led_brightness;
|
||||||
uint16_t debounce_delay;
|
uint16_t debounce_delay;
|
||||||
|
|
||||||
uint8_t _padding[m_store_size - sizeof(uint8_t) - sizeof(usb_mode_t) -
|
uint8_t _padding[m_store_size - sizeof(uint8_t) - sizeof(usb_mode_t) -
|
||||||
sizeof(Peripherals::Drum::Config::Thresholds) - sizeof(uint8_t) - sizeof(uint8_t) -
|
sizeof(Peripherals::Drum::Config::Thresholds) - sizeof(uint8_t) - sizeof(uint16_t)];
|
||||||
sizeof(uint16_t)];
|
|
||||||
};
|
};
|
||||||
static_assert(sizeof(Storecache) == m_store_size);
|
static_assert(sizeof(Storecache) == m_store_size);
|
||||||
|
|
||||||
@ -53,9 +51,6 @@ class SettingsStore {
|
|||||||
void setTriggerThresholds(const Peripherals::Drum::Config::Thresholds &thresholds);
|
void setTriggerThresholds(const Peripherals::Drum::Config::Thresholds &thresholds);
|
||||||
Peripherals::Drum::Config::Thresholds getTriggerThresholds();
|
Peripherals::Drum::Config::Thresholds getTriggerThresholds();
|
||||||
|
|
||||||
void setTriggerThresholdScaleLevel(const uint8_t threshold_scale_level);
|
|
||||||
uint8_t getTriggerThresholdScaleLevel();
|
|
||||||
|
|
||||||
void setLedBrightness(const uint8_t brightness);
|
void setLedBrightness(const uint8_t brightness);
|
||||||
uint8_t getLedBrightness();
|
uint8_t getLedBrightness();
|
||||||
|
|
||||||
|
@ -92,8 +92,6 @@ void core1_task() {
|
|||||||
|
|
||||||
led.update();
|
led.update();
|
||||||
display.update();
|
display.update();
|
||||||
|
|
||||||
// sleep_ms(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,7 +129,6 @@ int main() {
|
|||||||
|
|
||||||
drum.setDebounceDelay(settings_store->getDebounceDelay());
|
drum.setDebounceDelay(settings_store->getDebounceDelay());
|
||||||
drum.setThresholds(settings_store->getTriggerThresholds());
|
drum.setThresholds(settings_store->getTriggerThresholds());
|
||||||
drum.setThresholdScaleLevel(settings_store->getTriggerThresholdScaleLevel());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
readSettings();
|
readSettings();
|
||||||
|
@ -49,9 +49,9 @@ Drum::ExternalAdc::ExternalAdc(const Drum::Config::Spi &spi_config) : m_mcp3204(
|
|||||||
|
|
||||||
uint16_t Drum::ExternalAdc::read(uint8_t channel) { return m_mcp3204.read(channel); }
|
uint16_t Drum::ExternalAdc::read(uint8_t channel) { return m_mcp3204.read(channel); }
|
||||||
|
|
||||||
Drum::Pad::Pad(uint8_t channel) : channel(channel), last_change(0), active(false) {}
|
Drum::Pad::Pad(const uint8_t channel) : channel(channel), last_change(0), active(false) {}
|
||||||
|
|
||||||
void Drum::Pad::setState(bool state, uint16_t debounce_delay) {
|
void Drum::Pad::setState(const bool state, const uint16_t debounce_delay) {
|
||||||
if (active == state) {
|
if (active == state) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -99,28 +99,37 @@ void Drum::updateInputState(Utils::InputState &input_state) {
|
|||||||
// Oversample ADC inputs to get rid of ADC noise
|
// Oversample ADC inputs to get rid of ADC noise
|
||||||
const auto raw_values = sampleInputs();
|
const auto raw_values = sampleInputs();
|
||||||
|
|
||||||
const auto max_value = std::max_element(raw_values.cbegin(), raw_values.cend(),
|
auto get_threshold = [&](const Id target) {
|
||||||
[](const auto a, const auto b) { return a.second < b.second; });
|
switch (target) {
|
||||||
|
case Id::DON_LEFT:
|
||||||
auto do_set_state = [&](const auto &id, const auto &threshold) {
|
return m_config.trigger_thresholds.don_left;
|
||||||
// Increase threshold for very hard hits to avoid false inputs on neighboring pads
|
case Id::DON_RIGHT:
|
||||||
float mult = 1.0;
|
return m_config.trigger_thresholds.don_right;
|
||||||
if (id != max_value->first && m_config.trigger_threshold_scale_level > 0) {
|
case Id::KA_LEFT:
|
||||||
mult = float(max_value->second) / (((UINT8_MAX * 16) - (m_config.trigger_threshold_scale_level * 16)) + 1);
|
return m_config.trigger_thresholds.ka_left;
|
||||||
mult = mult < 1.0 ? 1.0 : mult;
|
case Id::KA_RIGHT:
|
||||||
}
|
return m_config.trigger_thresholds.ka_right;
|
||||||
|
case Id::NONE:
|
||||||
if (raw_values.at(id) > (threshold * mult)) {
|
return (uint16_t)0;
|
||||||
m_pads.at(id).setState(true, m_config.debounce_delay_ms);
|
|
||||||
} else {
|
|
||||||
m_pads.at(id).setState(false, m_config.debounce_delay_ms);
|
|
||||||
}
|
}
|
||||||
|
return (uint16_t)0;
|
||||||
};
|
};
|
||||||
|
|
||||||
do_set_state(Id::DON_LEFT, m_config.trigger_thresholds.don_left);
|
// Consider the hardest hit pad the one that actually was hit,
|
||||||
do_set_state(Id::KA_LEFT, m_config.trigger_thresholds.ka_left);
|
const auto max_hit = std::max_element(raw_values.cbegin(), raw_values.cend(),
|
||||||
do_set_state(Id::DON_RIGHT, m_config.trigger_thresholds.don_right);
|
[](const auto a, const auto b) { return a.second < b.second; });
|
||||||
do_set_state(Id::KA_RIGHT, m_config.trigger_thresholds.ka_right);
|
|
||||||
|
if (max_hit->second > get_threshold(max_hit->first)) {
|
||||||
|
m_pads.at(max_hit->first).setState(true, m_config.debounce_delay_ms);
|
||||||
|
} else {
|
||||||
|
m_pads.at(max_hit->first).setState(false, m_config.debounce_delay_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &input : raw_values) {
|
||||||
|
if (input.first != max_hit->first) {
|
||||||
|
m_pads.at(input.first).setState(false, m_config.debounce_delay_ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
input_state.drum.don_left.raw = raw_values.at(Id::DON_LEFT);
|
input_state.drum.don_left.raw = raw_values.at(Id::DON_LEFT);
|
||||||
input_state.drum.ka_left.raw = raw_values.at(Id::KA_LEFT);
|
input_state.drum.ka_left.raw = raw_values.at(Id::KA_LEFT);
|
||||||
@ -137,8 +146,4 @@ void Drum::setDebounceDelay(const uint16_t delay) { m_config.debounce_delay_ms =
|
|||||||
|
|
||||||
void Drum::setThresholds(const Config::Thresholds &thresholds) { m_config.trigger_thresholds = thresholds; }
|
void Drum::setThresholds(const Config::Thresholds &thresholds) { m_config.trigger_thresholds = thresholds; }
|
||||||
|
|
||||||
void Drum::setThresholdScaleLevel(const uint8_t threshold_scale_level) {
|
|
||||||
m_config.trigger_threshold_scale_level = threshold_scale_level;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Doncon::Peripherals
|
} // namespace Doncon::Peripherals
|
||||||
|
@ -28,15 +28,14 @@ const std::map<Menu::Page, const Menu::Descriptor> Menu::descriptors = {
|
|||||||
{"Debug", Menu::Descriptor::Action::ChangeUsbModeDebug}}, //
|
{"Debug", Menu::Descriptor::Action::ChangeUsbModeDebug}}, //
|
||||||
0}}, //
|
0}}, //
|
||||||
|
|
||||||
{Menu::Page::TriggerThreshold, //
|
{Menu::Page::TriggerThreshold, //
|
||||||
{Menu::Descriptor::Type::Selection, //
|
{Menu::Descriptor::Type::Selection, //
|
||||||
"Sensitivity", //
|
"Sensitivity", //
|
||||||
{{"Ka Left", Menu::Descriptor::Action::GotoPageTriggerThresholdKaLeft}, //
|
{{"Ka Left", Menu::Descriptor::Action::GotoPageTriggerThresholdKaLeft}, //
|
||||||
{"Don Left", Menu::Descriptor::Action::GotoPageTriggerThresholdDonLeft}, //
|
{"Don Left", Menu::Descriptor::Action::GotoPageTriggerThresholdDonLeft}, //
|
||||||
{"Don Right", Menu::Descriptor::Action::GotoPageTriggerThresholdDonRight}, //
|
{"Don Right", Menu::Descriptor::Action::GotoPageTriggerThresholdDonRight}, //
|
||||||
{"Ka Right", Menu::Descriptor::Action::GotoPageTriggerThresholdKaRight}, //
|
{"Ka Right", Menu::Descriptor::Action::GotoPageTriggerThresholdKaRight}}, //
|
||||||
{"Scale Lvl", Menu::Descriptor::Action::GotoPageTriggerThresholdScaleLevel}}, //
|
0}}, //
|
||||||
0}}, //
|
|
||||||
|
|
||||||
{Menu::Page::TriggerThresholdKaLeft, //
|
{Menu::Page::TriggerThresholdKaLeft, //
|
||||||
{Menu::Descriptor::Type::Value, //
|
{Menu::Descriptor::Type::Value, //
|
||||||
@ -62,12 +61,6 @@ const std::map<Menu::Page, const Menu::Descriptor> Menu::descriptors = {
|
|||||||
{{"", Menu::Descriptor::Action::SetTriggerThresholdKaRight}}, //
|
{{"", Menu::Descriptor::Action::SetTriggerThresholdKaRight}}, //
|
||||||
4095}},
|
4095}},
|
||||||
|
|
||||||
{Menu::Page::TriggerThresholdScaleLevel, //
|
|
||||||
{Menu::Descriptor::Type::Value, //
|
|
||||||
"Sensitivity Scale Lvl", //
|
|
||||||
{{"", Menu::Descriptor::Action::SetTriggerThresholdScaleLevel}}, //
|
|
||||||
UINT8_MAX}},
|
|
||||||
|
|
||||||
{Menu::Page::DebounceDelay, //
|
{Menu::Page::DebounceDelay, //
|
||||||
{Menu::Descriptor::Type::Value, //
|
{Menu::Descriptor::Type::Value, //
|
||||||
"Hit Hold Time (ms)", //
|
"Hit Hold Time (ms)", //
|
||||||
@ -202,9 +195,6 @@ uint16_t Menu::getCurrentSelection(Menu::Page page) {
|
|||||||
case Page::TriggerThresholdKaRight:
|
case Page::TriggerThresholdKaRight:
|
||||||
return m_store->getTriggerThresholds().ka_right;
|
return m_store->getTriggerThresholds().ka_right;
|
||||||
break;
|
break;
|
||||||
case Page::TriggerThresholdScaleLevel:
|
|
||||||
return m_store->getTriggerThresholdScaleLevel();
|
|
||||||
break;
|
|
||||||
case Page::DebounceDelay:
|
case Page::DebounceDelay:
|
||||||
return m_store->getDebounceDelay();
|
return m_store->getDebounceDelay();
|
||||||
break;
|
break;
|
||||||
@ -252,9 +242,6 @@ void Menu::performSelectionAction(Menu::Descriptor::Action action) {
|
|||||||
case Descriptor::Action::GotoPageTriggerThresholdKaRight:
|
case Descriptor::Action::GotoPageTriggerThresholdKaRight:
|
||||||
gotoPage(Page::TriggerThresholdKaRight);
|
gotoPage(Page::TriggerThresholdKaRight);
|
||||||
break;
|
break;
|
||||||
case Descriptor::Action::GotoPageTriggerThresholdScaleLevel:
|
|
||||||
gotoPage(Page::TriggerThresholdScaleLevel);
|
|
||||||
break;
|
|
||||||
case Descriptor::Action::GotoPageLedBrightness:
|
case Descriptor::Action::GotoPageLedBrightness:
|
||||||
gotoPage(Page::LedBrightness);
|
gotoPage(Page::LedBrightness);
|
||||||
break;
|
break;
|
||||||
@ -307,7 +294,6 @@ void Menu::performSelectionAction(Menu::Descriptor::Action action) {
|
|||||||
case Descriptor::Action::SetTriggerThresholdDonLeft:
|
case Descriptor::Action::SetTriggerThresholdDonLeft:
|
||||||
case Descriptor::Action::SetTriggerThresholdDonRight:
|
case Descriptor::Action::SetTriggerThresholdDonRight:
|
||||||
case Descriptor::Action::SetTriggerThresholdKaRight:
|
case Descriptor::Action::SetTriggerThresholdKaRight:
|
||||||
case Descriptor::Action::SetTriggerThresholdScaleLevel:
|
|
||||||
gotoParent();
|
gotoParent();
|
||||||
break;
|
break;
|
||||||
case Descriptor::Action::SetDebounceDelay:
|
case Descriptor::Action::SetDebounceDelay:
|
||||||
@ -359,9 +345,6 @@ void Menu::performValueAction(Menu::Descriptor::Action action, uint16_t value) {
|
|||||||
thresholds.ka_right = value;
|
thresholds.ka_right = value;
|
||||||
m_store->setTriggerThresholds(thresholds);
|
m_store->setTriggerThresholds(thresholds);
|
||||||
} break;
|
} break;
|
||||||
case Descriptor::Action::SetTriggerThresholdScaleLevel:
|
|
||||||
m_store->setTriggerThresholdScaleLevel(value);
|
|
||||||
break;
|
|
||||||
case Descriptor::Action::SetDebounceDelay:
|
case Descriptor::Action::SetDebounceDelay:
|
||||||
m_store->setDebounceDelay(value);
|
m_store->setDebounceDelay(value);
|
||||||
break;
|
break;
|
||||||
|
@ -14,7 +14,6 @@ SettingsStore::SettingsStore()
|
|||||||
: m_store_cache({m_magic_byte,
|
: m_store_cache({m_magic_byte,
|
||||||
Config::Default::usb_mode,
|
Config::Default::usb_mode,
|
||||||
Config::Default::drum_config.trigger_thresholds,
|
Config::Default::drum_config.trigger_thresholds,
|
||||||
Config::Default::drum_config.trigger_threshold_scale_level,
|
|
||||||
Config::Default::led_config.brightness,
|
Config::Default::led_config.brightness,
|
||||||
Config::Default::drum_config.debounce_delay_ms,
|
Config::Default::drum_config.debounce_delay_ms,
|
||||||
{}}),
|
{}}),
|
||||||
@ -59,14 +58,6 @@ void SettingsStore::setTriggerThresholds(const Peripherals::Drum::Config::Thresh
|
|||||||
}
|
}
|
||||||
Peripherals::Drum::Config::Thresholds SettingsStore::getTriggerThresholds() { return m_store_cache.trigger_thresholds; }
|
Peripherals::Drum::Config::Thresholds SettingsStore::getTriggerThresholds() { return m_store_cache.trigger_thresholds; }
|
||||||
|
|
||||||
void SettingsStore::setTriggerThresholdScaleLevel(const uint8_t threshold_scale_level) {
|
|
||||||
if (threshold_scale_level != m_store_cache.trigger_threshold_scale_level) {
|
|
||||||
m_store_cache.trigger_threshold_scale_level = threshold_scale_level;
|
|
||||||
m_dirty = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uint8_t SettingsStore::getTriggerThresholdScaleLevel() { return m_store_cache.trigger_threshold_scale_level; }
|
|
||||||
|
|
||||||
void SettingsStore::setLedBrightness(const uint8_t brightness) {
|
void SettingsStore::setLedBrightness(const uint8_t brightness) {
|
||||||
if (m_store_cache.led_brightness != brightness) {
|
if (m_store_cache.led_brightness != brightness) {
|
||||||
m_store_cache.led_brightness = brightness;
|
m_store_cache.led_brightness = brightness;
|
||||||
|
Loading…
Reference in New Issue
Block a user