diff --git a/Firmware/OpeNITHM/AutoTouchboard.cpp b/Firmware/OpeNITHM/AutoTouchboard.cpp index 009db49..e577b9b 100644 --- a/Firmware/OpeNITHM/AutoTouchboard.cpp +++ b/Firmware/OpeNITHM/AutoTouchboard.cpp @@ -61,21 +61,18 @@ void AutoTouchboard::calibrateKeys() } // Take the initial baseline readings so we can populate our delta buffer - int value; + scan(); - for (int r = 0; r < NUM_READINGS; r++) { - scan(); - - for (int i = 0; i < NUM_SENSORS; i++) { - value = key_values[i]; - - // calculate the newest delta if it's not the first reading - if (r > 0) { - deltas[i]->addValue(value - lastReadings[i]); - } - - lastReadings[i] = value; - } + int value; + // take some initial readings before the main loop so we can establish baselines + for (int i = 0; i < NUM_SENSORS; i++) { + // determine the current thresholds for trigger + // and release based on the configured delta threhsold + // and the current readings + value = key_values[i]; + + states[i] = UNPRESSED; + calcThresholds(i, value); } // Flash the slider green for a couple of seconds to show success @@ -96,51 +93,35 @@ KeyState AutoTouchboard::update(int key) { // check if the button is pressed // keep a running record of the last X deltas and the latest readings - int value = key_values[key]; - deltas[key]->addValue(value - lastReadings[key]); - lastReadings[key] = value; - bool deltaTriggered = (deltas[key]->getSum() > deltaThreshold); + int pressure = key_values[key]; + unsigned long currMillis = millis(); + if (states[key] == UNPRESSED) { + // new press detected + if (pressure > triggerThresholdsDouble[key]) { + lastTriggerTimes[key] = currMillis; + states[key] = DOUBLE_PRESS; + } else if (pressure > triggerThresholdsSingle[key]) { + lastTriggerTimes[key] = currMillis; + states[key] = SINGLE_PRESS; + // the key hasn't been triggered, so we'll check how long it's been since + // the last trigger. if it's been more than the configured period, re-establish + // baselines for thresholds + } else if (currMillis - lastTriggerTimes[key] > CALIBRATION_PERIOD) { + calcThresholds(key, pressure); + } + // new release detected + } else if (states[key] != UNPRESSED) { + if (pressure < releaseThresholdsSingle[key]) { + states[key] = UNPRESSED; + } else if (pressure < releaseThresholdsDouble[key]) { + states[key] = SINGLE_PRESS; + } + } + #if NUM_SENSORS == 32 - // check the readout data and the running sum of the deltas; - // if running sum of deltas goes above our defined threshold, - // trigger a press and set new lower bounds for release, - // otherwise, check for a release - if (states[key] == UNPRESSED && deltaTriggered) { - // set a new release threshold based on the reading at the time we detected - // the press (minus the threshold + a small hysteresis factor) - releaseThresholdsSingle[key] = value - deltaThreshold + releaseHysteresis; - states[key] = SINGLE_PRESS; - } else if (states[key] != UNPRESSED && (value < releaseThresholdsSingle[key])) { - // new release - states[key] = UNPRESSED; - releaseThresholdsSingle[key] = 0; - } -#elif NUM_SENSORS == 16 - // check for new single press - if (states[key] == UNPRESSED && deltaTriggered) { - // set a new single release threshold based on the reading at the time we detected - // the press (minus the threshold + a small hysteresis factor) - releaseThresholdsSingle[key] = value - deltaThreshold + releaseHysteresis; - states[key] = SINGLE_PRESS; - } - // check for new double press - else if (states[key] == SINGLE_PRESS && deltaTriggered) { - // set a new release threshold based on the reading at the time we detected - // the press (minus the threshold + a small hysteresis factor) - releaseThresholdsDouble[key] = value - deltaThreshold + releaseHysteresis; - states[key] = DOUBLE_PRESS; - } - // check for double -> single release - else if (states[key] == DOUBLE_PRESS && (value < releaseThresholdsDouble[key]) && (value > releaseThresholdsSingle[key])) { - states[key] = SINGLE_PRESS; - releaseThresholdsDouble[key] = 0; - } - // check for any press (single or double) to no press) - else if (states[key] != UNPRESSED && value < releaseThresholdsSingle[key]) { - states[key] = UNPRESSED; - releaseThresholdsSingle[key] = 0; - releaseThresholdsDouble[key] = 0; + if (states[key] == DOUBLE_PRESS) { + states[key] == SINGLE_PRESS; } #endif @@ -152,16 +133,20 @@ uint16_t AutoTouchboard::getRawValue(int key) return key_values[key]; } +void AutoTouchboard::calcThresholds(int key, int pressure) +{ + triggerThresholdsSingle[key] = pressure + deltaThreshold; + releaseThresholdsSingle[key] = pressure + (deltaThreshold * releaseThreshold); + triggerThresholdsDouble[key] = triggerThresholdsSingle[key] + (0.8 * deltaThreshold); + releaseThresholdsDouble[key] = triggerThresholdsSingle[key] + (0.8 * deltaThreshold * releaseThreshold); + lastTriggerTimes[key] = millis(); +} + AutoTouchboard::AutoTouchboard() { pinMode(MUX_0, OUTPUT); pinMode(MUX_1, OUTPUT); pinMode(MUX_2, OUTPUT); - - for (int i = 0; i < NUM_SENSORS; i++) { - deltas[i] = new RunningSum(NUM_READINGS); - states[i] = UNPRESSED; - } - + calibrateKeys(); } diff --git a/Firmware/OpeNITHM/AutoTouchboard.h b/Firmware/OpeNITHM/AutoTouchboard.h index 9473f94..5cb0eaa 100644 --- a/Firmware/OpeNITHM/AutoTouchboard.h +++ b/Firmware/OpeNITHM/AutoTouchboard.h @@ -5,7 +5,6 @@ #include "Config.h" #include "PinConfig.h" -#include "RunningSum.h" #include "USBOutput.h" #include @@ -26,8 +25,7 @@ extern CRGB leds[16]; extern CRGB leds[31]; #endif -// the size of the buffer of deltas to keep for each key -#define NUM_READINGS 10 +#define CALIBRATION_PERIOD 15000 class AutoTouchboard { @@ -35,18 +33,20 @@ class AutoTouchboard // these will be tunable / need to be experimented with #if NUM_SENSORS == 32 int deltaThreshold = 4; - int releaseHysteresis = 1; + double releaseThreshold = 0.8; #else int deltaThreshold = 6; - int releaseHysteresis = 2; + double releaseThreshold = 0.8; #endif uint16_t key_values[NUM_SENSORS]; KeyState states[NUM_SENSORS]; + int triggerThresholdsSingle[NUM_SENSORS]; int releaseThresholdsSingle[NUM_SENSORS]; + int triggerThresholdsDouble[NUM_SENSORS]; int releaseThresholdsDouble[NUM_SENSORS]; - int lastReadings[NUM_SENSORS]; - RunningSum* deltas[NUM_SENSORS]; + unsigned long lastTriggerTimes[NUM_SENSORS]; + void calcThresholds(int key, int pressure); public: AutoTouchboard(); diff --git a/Firmware/OpeNITHM/RunningSum.cpp b/Firmware/OpeNITHM/RunningSum.cpp deleted file mode 100644 index 83af88d..0000000 --- a/Firmware/OpeNITHM/RunningSum.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "RunningSum.h" -#include - -RunningSum::RunningSum(int n) { - _size = n; - _ar = (int*) malloc(_size * sizeof(int)); - if (_ar == NULL) _size = 0; - clear(); -} - -RunningSum::~RunningSum() { - if (_ar != NULL) free(_ar); -} - -void RunningSum::clear() { - _cnt = 0; - _idx = 0; - _sum = 0.0; - for (int i = 0; i< _size; i++) _ar[i] = 0; -} - -void RunningSum::addValue(int f) { - if (_ar == NULL) return; - _sum -= _ar[_idx]; - _ar[_idx] = f; - _sum += f; - _idx++; - if (_idx == _size) _idx = 0; - if (_cnt < _size) _cnt++; -} diff --git a/Firmware/OpeNITHM/RunningSum.h b/Firmware/OpeNITHM/RunningSum.h deleted file mode 100644 index 8c9f247..0000000 --- a/Firmware/OpeNITHM/RunningSum.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef RunningSum_h -#define RunningSum_h - -#include "Arduino.h" - -class RunningSum -{ -public: - RunningSum(void); - RunningSum(int); - ~RunningSum(); - - void clear(); - void addValue(int); - - uint8_t getCount() { return _cnt; } - int getSum() { return _sum; } - -protected: - uint8_t _size; - uint8_t _cnt; - uint8_t _idx; - int _sum; - int * _ar; -}; - -#endif