Skip to content

Commit 4e739db

Browse files
authored
feat: improve input detection
1 parent 80ca0a9 commit 4e739db

2 files changed

Lines changed: 102 additions & 44 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,4 @@ soxstatic/
6868

6969
zeptocore.uf2
7070
pico-examples
71+
ectocore.uf2

lib/ectocore.h

Lines changed: 101 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@
1313
#define KNOB_ATTEN_ZERO_WIDTH 80
1414
#define DEBOUNCE_FILE_SWITCH 500
1515

16+
// Input detection configuration
17+
#define SIGNAL_SETTLE_TIME_US 8 // Time for signal to settle
18+
#define SIGNAL_READ_SAMPLES 1 // Number of samples to average
19+
#define DETECTION_THRESHOLD 5 // Consecutive matches needed for state change
20+
#define SIGNAL_THRESHOLD_MARGIN 50 // ADC counts above/below mean for detection
21+
#define MEAN_ALPHA 0.1f // EMA coefficient for mean signal
22+
#define DETECTION_INTERVAL_MS 10 // Minimum time between detection runs
23+
#define MEAN_SIGNAL_INTERVAL_MS 1000 // Time between mean signal recalculations
24+
#define SIGNAL_ERROR_TOLERANCE 2 // Allow N bit errors in pattern matching
25+
1626
typedef struct EctocoreFlash {
1727
uint16_t center_calibration[8];
1828
} EctocoreFlash;
@@ -450,16 +460,20 @@ void __not_in_flash_func(input_handling)() {
450460
uint8_t debounce_trig = 0;
451461
Saturation_setActive(saturation, sf->fx_active[FX_SATURATE]);
452462

453-
uint16_t debounce_input_detection = 0;
454-
uint16_t debounce_mean_signal = 0;
455-
uint16_t mean_signal = 0;
456-
const uint8_t length_signal = 9;
457-
uint8_t magic_signal[3][10] = {
458-
{0, 1, 1, 0, 1, 1, 0, 1, 0, 0},
459-
{0, 0, 1, 0, 1, 1, 0, 0, 1, 1},
460-
{1, 0, 0, 1, 0, 1, 0, 1, 1, 1},
463+
uint32_t last_input_detection_time = 0;
464+
uint32_t last_mean_signal_time = 0;
465+
float mean_signal_ema = 0;
466+
const uint8_t length_signal = 16;
467+
// Improved magic signals with better Hamming distance
468+
uint8_t magic_signal[3][16] = {
469+
{0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0},
470+
{1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1},
471+
{0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1},
461472
};
462473
bool cv_was_unplugged[3] = {false, false, false};
474+
uint8_t cv_detection_count[3] = {0, 0, 0};
475+
uint16_t detection_errors[3] = {0, 0, 0};
476+
uint8_t signal_strength[3] = {0, 0, 0};
463477

464478
// update the knobs
465479
#define KNOB_NUM 5
@@ -687,81 +701,124 @@ void __not_in_flash_func(input_handling)() {
687701
}
688702
}
689703

690-
if (debounce_mean_signal > 0 && mean_signal > 0) {
691-
debounce_mean_signal--;
692-
} else {
693-
// calculate mean signal
704+
// Calculate mean signal using exponential moving average
705+
uint32_t current_time = to_ms_since_boot(get_absolute_time());
706+
if (current_time - last_mean_signal_time >= MEAN_SIGNAL_INTERVAL_MS) {
694707
int16_t total_mean_signal = 0;
695708
uint8_t total_signals_sent = 0;
696709
for (uint8_t j = 0; j < 3; j++) {
697710
if (!cv_plugged[j]) {
698711
total_signals_sent++;
699712
for (uint8_t i = 0; i < length_signal; i++) {
700713
gpio_put(GPIO_INPUTDETECT, magic_signal[j][i]);
701-
sleep_us(6);
714+
sleep_us(SIGNAL_SETTLE_TIME_US);
702715
total_mean_signal += MCP3208_read(mcp3208, cv_signals[j], false);
703716
}
704717
}
705718
}
706719
if (total_signals_sent > 0) {
707-
mean_signal = total_mean_signal / (total_signals_sent * length_signal);
708-
// printf("[ectocore] mean_signal: %d\n", mean_signal);
720+
float new_sample =
721+
(float)total_mean_signal / (total_signals_sent * length_signal);
722+
if (mean_signal_ema == 0) {
723+
mean_signal_ema = new_sample; // Initialize on first run
724+
} else {
725+
mean_signal_ema =
726+
MEAN_ALPHA * new_sample + (1.0f - MEAN_ALPHA) * mean_signal_ema;
727+
}
728+
// printf("[ectocore] mean_signal_ema: %f\n", mean_signal_ema);
709729
}
710-
debounce_mean_signal = 10000;
730+
last_mean_signal_time = current_time;
711731
}
712732

713-
if (debounce_input_detection > 0) {
714-
debounce_input_detection--;
715-
} else if (mean_signal > 0) {
716-
// input detection
717-
bool found_change = false;
733+
// Input detection with time-based debouncing
734+
if (mean_signal_ema > 0 &&
735+
current_time - last_input_detection_time >= DETECTION_INTERVAL_MS) {
718736
int16_t val_input;
719-
uint8_t response_signal[3][10] = {
720-
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
721-
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
722-
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
737+
uint8_t response_signal[3][16] = {
738+
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
739+
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
740+
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
723741
};
724742

725743
for (uint8_t j = 0; j < 3; j++) {
744+
int16_t total_signal_strength = 0;
726745
for (uint8_t i = 0; i < length_signal; i++) {
727746
gpio_put(GPIO_INPUTDETECT, magic_signal[j][i]);
728-
sleep_us(6);
747+
sleep_us(SIGNAL_SETTLE_TIME_US);
729748
val_input = MCP3208_read(mcp3208, cv_signals[j], false);
730-
if (val_input > mean_signal) {
749+
750+
// Track signal strength for diagnostics
751+
int16_t signal_diff = val_input - (int16_t)mean_signal_ema;
752+
total_signal_strength += abs(signal_diff);
753+
754+
// Threshold with margin to reduce noise sensitivity
755+
if (val_input > (int16_t)mean_signal_ema + SIGNAL_THRESHOLD_MARGIN) {
731756
response_signal[j][i] = 1;
757+
} else if (val_input <
758+
(int16_t)mean_signal_ema - SIGNAL_THRESHOLD_MARGIN) {
759+
response_signal[j][i] = 0;
760+
} else {
761+
// Ambiguous reading - use previous state or default to 0
762+
response_signal[j][i] = 0;
732763
}
733-
// if (j == 0) {
734-
// printf("%d ", val_input);
735-
// }
736764
}
737-
// if (j == 0) {
738-
// printf("\n");
739-
// }
765+
// Store average signal strength
766+
signal_strength[j] = total_signal_strength / length_signal;
740767
}
768+
769+
// Validate signals with error correction
741770
bool is_signal[3] = {true, true, true};
742771
for (uint8_t j = 0; j < 3; j++) {
772+
uint8_t count_matches = 0;
743773
for (uint8_t i = 0; i < length_signal; i++) {
744-
if (response_signal[j][i] != magic_signal[j][i]) {
745-
is_signal[j] = false;
746-
break;
774+
if (response_signal[j][i] == magic_signal[j][i]) {
775+
count_matches++;
747776
}
748777
}
778+
// Allow SIGNAL_ERROR_TOLERANCE bit errors
779+
is_signal[j] =
780+
(count_matches >= length_signal - SIGNAL_ERROR_TOLERANCE);
781+
if (!is_signal[j] &&
782+
count_matches < length_signal - SIGNAL_ERROR_TOLERANCE) {
783+
detection_errors[j]++;
784+
}
749785
}
786+
787+
// Hysteresis-based state machine
750788
for (uint8_t j = 0; j < 3; j++) {
751789
if (!is_signal[j] && !cv_plugged[j]) {
752-
printf("[ectocore] cv_%d plugged\n", j);
753-
debounce_mean_signal = 10;
790+
// Potential plug-in detected
791+
cv_detection_count[j]++;
792+
if (cv_detection_count[j] >= DETECTION_THRESHOLD) {
793+
cv_plugged[j] = true;
794+
cv_detection_count[j] = 0;
795+
last_mean_signal_time = 0; // Trigger mean recalculation
796+
printf("[ectocore] cv_%d plugged\n", j);
797+
}
754798
} else if (is_signal[j] && cv_plugged[j]) {
755-
printf("[ectocore] cv_%d unplugged\n", j);
756-
debounce_mean_signal = 10;
757-
cv_was_unplugged[j] = true;
799+
// Potential unplug detected
800+
cv_detection_count[j]++;
801+
if (cv_detection_count[j] >= DETECTION_THRESHOLD) {
802+
cv_plugged[j] = false;
803+
cv_detection_count[j] = 0;
804+
cv_was_unplugged[j] = true;
805+
last_mean_signal_time = 0; // Trigger mean recalculation
806+
printf("[ectocore] cv_%d unplugged\n", j);
807+
}
808+
} else {
809+
// State matches expectation - reset counter
810+
cv_detection_count[j] = 0;
758811
}
759-
cv_plugged[j] = !is_signal[j];
760812
}
761-
debounce_input_detection = 100;
813+
814+
last_input_detection_time = current_time;
762815
}
763816

764817
// update the cv for each channel
818+
// Ensure GPIO_INPUTDETECT is LOW to prevent race condition
819+
gpio_put(GPIO_INPUTDETECT, 0);
820+
sleep_us(SIGNAL_SETTLE_TIME_US);
821+
765822
for (uint8_t i = 0; i < 3; i++) {
766823
if (cv_plugged[i]) {
767824
// collect out CV values
@@ -873,7 +930,7 @@ void __not_in_flash_func(input_handling)() {
873930
}
874931
}
875932

876-
uint32_t current_time = to_ms_since_boot(get_absolute_time());
933+
current_time = to_ms_since_boot(get_absolute_time());
877934

878935
if (debounce_file_change > 0) {
879936
if (debounce_file_switching > 0) {

0 commit comments

Comments
 (0)