From 092eeb4f07d9e0f5a10f5a60db173199e58bc07f Mon Sep 17 00:00:00 2001 From: Frederik Walk Date: Sun, 3 Dec 2023 15:34:57 +0100 Subject: [PATCH] Simplify false hit detection For now, only allow one input at a time --- README.md | 11 ++----- include/GlobalConfiguration.h | 3 +- include/peripherals/Drum.h | 7 ++--- include/utils/Menu.h | 3 -- include/utils/SettingsStore.h | 7 +---- src/main.cpp | 3 -- src/peripherals/Drum.cpp | 55 +++++++++++++++++++---------------- src/utils/Menu.cpp | 33 +++++---------------- src/utils/SettingsStore.cpp | 9 ------ 9 files changed, 45 insertions(+), 86 deletions(-) diff --git a/README.md b/README.md index 552c3bc..d76e711 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,8 @@ Few things which you probably want to change more regularly can be changed using - Controller emulation mode - LED brightness -- Trigger thresholds and scale level +- Trigger thresholds +- Hold Time - 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. @@ -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. -### 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 ### IO Board diff --git a/include/GlobalConfiguration.h b/include/GlobalConfiguration.h index c515b7e..89a2aa4 100644 --- a/include/GlobalConfiguration.h +++ b/include/GlobalConfiguration.h @@ -44,9 +44,8 @@ const Peripherals::Drum::Config drum_config = { 80, // Don Right 50, // Ka Right }, - 230, // Trigger threshold scale level - 50, // ADC sample count + 10, // ADC sample count 25, // Debounce delay in milliseconds true, // Use external ADC diff --git a/include/peripherals/Drum.h b/include/peripherals/Drum.h index 9bfbdcd..b424b30 100644 --- a/include/peripherals/Drum.h +++ b/include/peripherals/Drum.h @@ -32,7 +32,6 @@ class Drum { AdcInputs adc_inputs; Thresholds trigger_thresholds; - uint8_t trigger_threshold_scale_level; uint8_t sample_count; uint16_t debounce_delay_ms; @@ -51,6 +50,7 @@ class Drum { private: enum class Id { + NONE, DON_LEFT, KA_LEFT, DON_RIGHT, @@ -64,11 +64,11 @@ class Drum { bool active; public: - Pad(uint8_t channel); + Pad(const uint8_t channel); uint8_t getChannel() const { return channel; }; 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 { @@ -105,7 +105,6 @@ class Drum { void setDebounceDelay(const uint16_t delay); void setThresholds(const Config::Thresholds &thresholds); - void setThresholdScaleLevel(const uint8_t threshold_scale_level); }; } // namespace Doncon::Peripherals diff --git a/include/utils/Menu.h b/include/utils/Menu.h index 59abcc8..cb72a06 100644 --- a/include/utils/Menu.h +++ b/include/utils/Menu.h @@ -23,7 +23,6 @@ class Menu { TriggerThresholdDonLeft, TriggerThresholdDonRight, TriggerThresholdKaRight, - TriggerThresholdScaleLevel, DebounceDelay, LedBrightness, Reset, @@ -54,7 +53,6 @@ class Menu { GotoPageTriggerThresholdDonLeft, GotoPageTriggerThresholdDonRight, GotoPageTriggerThresholdKaRight, - GotoPageTriggerThresholdScaleLevel, GotoPageDebounceDelay, GotoPageLedBrightness, GotoPageReset, @@ -74,7 +72,6 @@ class Menu { SetTriggerThresholdDonLeft, SetTriggerThresholdDonRight, SetTriggerThresholdKaRight, - SetTriggerThresholdScaleLevel, SetDebounceDelay, SetLedBrightness, diff --git a/include/utils/SettingsStore.h b/include/utils/SettingsStore.h index 6d0aa7a..e931c94 100644 --- a/include/utils/SettingsStore.h +++ b/include/utils/SettingsStore.h @@ -20,13 +20,11 @@ class SettingsStore { uint8_t in_use; usb_mode_t usb_mode; Peripherals::Drum::Config::Thresholds trigger_thresholds; - uint8_t trigger_threshold_scale_level; uint8_t led_brightness; uint16_t debounce_delay; 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(uint16_t)]; + sizeof(Peripherals::Drum::Config::Thresholds) - sizeof(uint8_t) - sizeof(uint16_t)]; }; static_assert(sizeof(Storecache) == m_store_size); @@ -53,9 +51,6 @@ class SettingsStore { void setTriggerThresholds(const Peripherals::Drum::Config::Thresholds &thresholds); Peripherals::Drum::Config::Thresholds getTriggerThresholds(); - void setTriggerThresholdScaleLevel(const uint8_t threshold_scale_level); - uint8_t getTriggerThresholdScaleLevel(); - void setLedBrightness(const uint8_t brightness); uint8_t getLedBrightness(); diff --git a/src/main.cpp b/src/main.cpp index 7e48c9c..bcb7cc0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -92,8 +92,6 @@ void core1_task() { led.update(); display.update(); - - // sleep_ms(1); } } @@ -131,7 +129,6 @@ int main() { drum.setDebounceDelay(settings_store->getDebounceDelay()); drum.setThresholds(settings_store->getTriggerThresholds()); - drum.setThresholdScaleLevel(settings_store->getTriggerThresholdScaleLevel()); }; readSettings(); diff --git a/src/peripherals/Drum.cpp b/src/peripherals/Drum.cpp index b07b8a1..8350d38 100644 --- a/src/peripherals/Drum.cpp +++ b/src/peripherals/Drum.cpp @@ -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); } -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) { return; } @@ -99,28 +99,37 @@ void Drum::updateInputState(Utils::InputState &input_state) { // Oversample ADC inputs to get rid of ADC noise const auto raw_values = sampleInputs(); - const auto max_value = std::max_element(raw_values.cbegin(), raw_values.cend(), - [](const auto a, const auto b) { return a.second < b.second; }); - - auto do_set_state = [&](const auto &id, const auto &threshold) { - // Increase threshold for very hard hits to avoid false inputs on neighboring pads - float mult = 1.0; - if (id != max_value->first && m_config.trigger_threshold_scale_level > 0) { - mult = float(max_value->second) / (((UINT8_MAX * 16) - (m_config.trigger_threshold_scale_level * 16)) + 1); - mult = mult < 1.0 ? 1.0 : mult; - } - - if (raw_values.at(id) > (threshold * mult)) { - m_pads.at(id).setState(true, m_config.debounce_delay_ms); - } else { - m_pads.at(id).setState(false, m_config.debounce_delay_ms); + auto get_threshold = [&](const Id target) { + switch (target) { + case Id::DON_LEFT: + return m_config.trigger_thresholds.don_left; + case Id::DON_RIGHT: + return m_config.trigger_thresholds.don_right; + case Id::KA_LEFT: + return m_config.trigger_thresholds.ka_left; + case Id::KA_RIGHT: + return m_config.trigger_thresholds.ka_right; + case Id::NONE: + return (uint16_t)0; } + return (uint16_t)0; }; - do_set_state(Id::DON_LEFT, m_config.trigger_thresholds.don_left); - do_set_state(Id::KA_LEFT, m_config.trigger_thresholds.ka_left); - do_set_state(Id::DON_RIGHT, m_config.trigger_thresholds.don_right); - do_set_state(Id::KA_RIGHT, m_config.trigger_thresholds.ka_right); + // Consider the hardest hit pad the one that actually was hit, + const auto max_hit = std::max_element(raw_values.cbegin(), raw_values.cend(), + [](const auto a, const auto b) { return a.second < b.second; }); + + 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.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::setThresholdScaleLevel(const uint8_t threshold_scale_level) { - m_config.trigger_threshold_scale_level = threshold_scale_level; -} - } // namespace Doncon::Peripherals diff --git a/src/utils/Menu.cpp b/src/utils/Menu.cpp index 8cde3dc..274bd83 100644 --- a/src/utils/Menu.cpp +++ b/src/utils/Menu.cpp @@ -28,15 +28,14 @@ const std::map Menu::descriptors = { {"Debug", Menu::Descriptor::Action::ChangeUsbModeDebug}}, // 0}}, // - {Menu::Page::TriggerThreshold, // - {Menu::Descriptor::Type::Selection, // - "Sensitivity", // - {{"Ka Left", Menu::Descriptor::Action::GotoPageTriggerThresholdKaLeft}, // - {"Don Left", Menu::Descriptor::Action::GotoPageTriggerThresholdDonLeft}, // - {"Don Right", Menu::Descriptor::Action::GotoPageTriggerThresholdDonRight}, // - {"Ka Right", Menu::Descriptor::Action::GotoPageTriggerThresholdKaRight}, // - {"Scale Lvl", Menu::Descriptor::Action::GotoPageTriggerThresholdScaleLevel}}, // - 0}}, // + {Menu::Page::TriggerThreshold, // + {Menu::Descriptor::Type::Selection, // + "Sensitivity", // + {{"Ka Left", Menu::Descriptor::Action::GotoPageTriggerThresholdKaLeft}, // + {"Don Left", Menu::Descriptor::Action::GotoPageTriggerThresholdDonLeft}, // + {"Don Right", Menu::Descriptor::Action::GotoPageTriggerThresholdDonRight}, // + {"Ka Right", Menu::Descriptor::Action::GotoPageTriggerThresholdKaRight}}, // + 0}}, // {Menu::Page::TriggerThresholdKaLeft, // {Menu::Descriptor::Type::Value, // @@ -62,12 +61,6 @@ const std::map Menu::descriptors = { {{"", Menu::Descriptor::Action::SetTriggerThresholdKaRight}}, // 4095}}, - {Menu::Page::TriggerThresholdScaleLevel, // - {Menu::Descriptor::Type::Value, // - "Sensitivity Scale Lvl", // - {{"", Menu::Descriptor::Action::SetTriggerThresholdScaleLevel}}, // - UINT8_MAX}}, - {Menu::Page::DebounceDelay, // {Menu::Descriptor::Type::Value, // "Hit Hold Time (ms)", // @@ -202,9 +195,6 @@ uint16_t Menu::getCurrentSelection(Menu::Page page) { case Page::TriggerThresholdKaRight: return m_store->getTriggerThresholds().ka_right; break; - case Page::TriggerThresholdScaleLevel: - return m_store->getTriggerThresholdScaleLevel(); - break; case Page::DebounceDelay: return m_store->getDebounceDelay(); break; @@ -252,9 +242,6 @@ void Menu::performSelectionAction(Menu::Descriptor::Action action) { case Descriptor::Action::GotoPageTriggerThresholdKaRight: gotoPage(Page::TriggerThresholdKaRight); break; - case Descriptor::Action::GotoPageTriggerThresholdScaleLevel: - gotoPage(Page::TriggerThresholdScaleLevel); - break; case Descriptor::Action::GotoPageLedBrightness: gotoPage(Page::LedBrightness); break; @@ -307,7 +294,6 @@ void Menu::performSelectionAction(Menu::Descriptor::Action action) { case Descriptor::Action::SetTriggerThresholdDonLeft: case Descriptor::Action::SetTriggerThresholdDonRight: case Descriptor::Action::SetTriggerThresholdKaRight: - case Descriptor::Action::SetTriggerThresholdScaleLevel: gotoParent(); break; case Descriptor::Action::SetDebounceDelay: @@ -359,9 +345,6 @@ void Menu::performValueAction(Menu::Descriptor::Action action, uint16_t value) { thresholds.ka_right = value; m_store->setTriggerThresholds(thresholds); } break; - case Descriptor::Action::SetTriggerThresholdScaleLevel: - m_store->setTriggerThresholdScaleLevel(value); - break; case Descriptor::Action::SetDebounceDelay: m_store->setDebounceDelay(value); break; diff --git a/src/utils/SettingsStore.cpp b/src/utils/SettingsStore.cpp index 73764e0..c0008e1 100644 --- a/src/utils/SettingsStore.cpp +++ b/src/utils/SettingsStore.cpp @@ -14,7 +14,6 @@ SettingsStore::SettingsStore() : m_store_cache({m_magic_byte, Config::Default::usb_mode, Config::Default::drum_config.trigger_thresholds, - Config::Default::drum_config.trigger_threshold_scale_level, Config::Default::led_config.brightness, 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; } -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) { if (m_store_cache.led_brightness != brightness) { m_store_cache.led_brightness = brightness;