aboutsummaryrefslogtreecommitdiff
path: root/spaghetti-monster
diff options
context:
space:
mode:
authorSelene ToyKeeper2017-12-12 15:22:42 -0700
committerSelene ToyKeeper2017-12-12 15:22:42 -0700
commit8c13fd82557dadbe81023c534cd19c31ec40bde4 (patch)
tree540cab9fb6a09153fb99f8e5500aa670cb0b3fcb /spaghetti-monster
parentGreatly improved button debouncing. Helps a lot on FW3A and my light saber. (diff)
downloadanduril-8c13fd82557dadbe81023c534cd19c31ec40bde4.tar.gz
anduril-8c13fd82557dadbe81023c534cd19c31ec40bde4.tar.bz2
anduril-8c13fd82557dadbe81023c534cd19c31ec40bde4.zip
Debouncing finally works (at least, it does on my two test hosts).
Diffstat (limited to '')
-rw-r--r--spaghetti-monster/fsm-pcint.c40
-rw-r--r--spaghetti-monster/fsm-pcint.h1
-rw-r--r--spaghetti-monster/fsm-standby.c2
-rw-r--r--spaghetti-monster/fsm-wdt.c38
4 files changed, 25 insertions, 56 deletions
diff --git a/spaghetti-monster/fsm-pcint.c b/spaghetti-monster/fsm-pcint.c
index c04375a..722cb88 100644
--- a/spaghetti-monster/fsm-pcint.c
+++ b/spaghetti-monster/fsm-pcint.c
@@ -24,20 +24,19 @@
#include <util/delay_basic.h>
uint8_t button_is_pressed() {
- // debounce a little
- uint8_t highcount = 0;
- // measure for 16/64ths of a ms
- for(uint8_t i=0; i<BP_SAMPLES; i++) {
- // check current value
- uint8_t bit = ((PINB & (1<<SWITCH_PIN)) == 0);
- highcount += bit;
+ // remember the past 32 measurements
+ static uint32_t readings = 0;
+ // take at least one new measurement,
+ // and wait for measurements to settle to all zeroes or all ones
+ do {
+ // shift past readings and add current value
+ readings = (readings << 1) | ((PINB & (1<<SWITCH_PIN)) == 0);
// wait a moment
- _delay_loop_2(BOGOMIPS/64);
+ _delay_loop_2(BOGOMIPS/16); // up to 2ms to stabilize
}
- // use most common value
- uint8_t result = (highcount > (BP_SAMPLES/2));
- //button_was_pressed = result;
- return result;
+ while ((readings != 0) && (readings != 0xFFFFFFFF));
+ button_last_state = readings;
+ return readings;
}
inline void PCINT_on() {
@@ -59,20 +58,15 @@ ISR(PCINT0_vect) {
//DEBUG_FLASH;
- /*
- uint8_t pressed;
+ // as it turns out, it's more reliable to detect pin changes from WDT
+ // because PCINT itself tends to double-tap when connected to a
+ // noisy / bouncy switch (so the content of this function has been
+ // moved to a separate function, called from WDT only)
+ // PCINT_inner(button_is_pressed());
- // add event to current sequence
- pressed = button_is_pressed();
- PCINT_inner(pressed);
- */
- if (! PCINT_since_WDT) {
- PCINT_since_WDT = 1;
- PCINT_inner(button_is_pressed());
- }
}
-// should only be called from PCINT and WDT
+// should only be called from PCINT and/or WDT
// (is a separate function to reduce code duplication)
void PCINT_inner(uint8_t pressed) {
uint8_t pushed;
diff --git a/spaghetti-monster/fsm-pcint.h b/spaghetti-monster/fsm-pcint.h
index a94fc82..ec3ae4b 100644
--- a/spaghetti-monster/fsm-pcint.h
+++ b/spaghetti-monster/fsm-pcint.h
@@ -23,7 +23,6 @@
//static volatile uint8_t button_was_pressed;
#define BP_SAMPLES 32
volatile uint8_t button_last_state;
-volatile uint8_t PCINT_since_WDT;
uint8_t button_is_pressed();
inline void PCINT_on();
inline void PCINT_off();
diff --git a/spaghetti-monster/fsm-standby.c b/spaghetti-monster/fsm-standby.c
index eb631d6..b90ccea 100644
--- a/spaghetti-monster/fsm-standby.c
+++ b/spaghetti-monster/fsm-standby.c
@@ -37,7 +37,7 @@ void sleep_until_eswitch_pressed()
// make sure switch isn't currently pressed
while (button_is_pressed()) {}
empty_event_sequence(); // cancel pending input on suspend
- PCINT_since_WDT = 0; // ensure PCINT won't ignore itself
+ //PCINT_since_WDT = 0; // ensure PCINT won't ignore itself
PCINT_on(); // wake on e-switch event
diff --git a/spaghetti-monster/fsm-wdt.c b/spaghetti-monster/fsm-wdt.c
index bee2914..777bef0 100644
--- a/spaghetti-monster/fsm-wdt.c
+++ b/spaghetti-monster/fsm-wdt.c
@@ -45,47 +45,23 @@ inline void WDT_off()
// clock tick -- this runs every 16ms (62.5 fps)
ISR(WDT_vect) {
+ // detect and emit button change events
+ uint8_t was_pressed = button_last_state;
+ uint8_t pressed = button_is_pressed();
+ if (was_pressed != pressed) PCINT_inner(pressed);
+
//if (ticks_since_last_event < 0xff) ticks_since_last_event ++;
// increment, but loop from max back to half
ticks_since_last_event = (ticks_since_last_event + 1) \
| (ticks_since_last_event & 0x8000);
- // just in case the pin change interrupt missed something
- uint8_t le_num = last_event_num();
- uint8_t last_event = 0;
- if (le_num >= 1) last_event = current_event[le_num-1];
- uint8_t pressed = button_is_pressed();
- uint8_t was_pressed_before = (last_event == A_PRESS) || (last_event == A_HOLD);
- //if (pressed != button_last_state) {
- if (pressed != was_pressed_before) {
- PCINT_inner(pressed);
- /*
- uint8_t pushed;
- if (pressed) {
- pushed = push_event(A_PRESS);
- } else {
- pushed = push_event(A_RELEASE);
- }
-
- // check if sequence matches any defined sequences
- // if so, send event to current state callback
- if (pushed) {
- button_last_state = pressed;
- emit_current_event(0);
- }
- */
- }
- PCINT_since_WDT = 0;
-
// if time since last event exceeds timeout,
// append timeout to current event sequence, then
// send event to current state callback
// preload recent events
- //uint8_t le_num = last_event_num();
- le_num = last_event_num();
- //uint8_t last_event = 0;
- last_event = 0;
+ uint8_t le_num = last_event_num();
+ uint8_t last_event = 0;
uint8_t prev_event = 0;
if (le_num >= 1) last_event = current_event[le_num-1];
if (le_num >= 2) prev_event = current_event[le_num-2];