From 73a5a6974a98aa73ab392272b4d69d285c85dee5 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 19 Aug 2017 17:20:46 -0600 Subject: Completely reorganized SpaghettiMonster code into smaller logical pieces: fsm-*.c and fsm-*.h. --- spaghetti-monster/fsm-wdt.c | 107 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 spaghetti-monster/fsm-wdt.c (limited to 'spaghetti-monster/fsm-wdt.c') diff --git a/spaghetti-monster/fsm-wdt.c b/spaghetti-monster/fsm-wdt.c new file mode 100644 index 0000000..afcf467 --- /dev/null +++ b/spaghetti-monster/fsm-wdt.c @@ -0,0 +1,107 @@ +/* + * fsm-wdt.c: WDT (Watch Dog Timer) functions for SpaghettiMonster. + * + * Copyright (C) 2017 Selene ToyKeeper + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef FSM_WDT_C +#define FSM_WDT_C + +#include +#include + +void WDT_on() +{ + // interrupt every 16ms + //cli(); // Disable interrupts + wdt_reset(); // Reset the WDT + WDTCR |= (1<= 1) last_event = current_event[le_num-1]; + if (le_num >= 2) prev_event = current_event[le_num-2]; + + // user held button long enough to count as a long click? + if (last_event == A_PRESS) { + if (ticks_since_last_event >= HOLD_TIMEOUT) { + push_event(A_HOLD); + emit_current_event(0); + } + } + + // user is still holding button, so tick + else if (last_event == A_HOLD) { + emit_current_event(ticks_since_last_event); + } + + // detect completed button presses with expired timeout + else if (last_event == A_RELEASE) { + // no timeout required when releasing a long-press + // TODO? move this logic to PCINT() and simplify things here? + if (prev_event == A_HOLD) { + //emit_current_event(0); // should have been emitted by PCINT + empty_event_sequence(); + } + // end and clear event after release timeout + else if (ticks_since_last_event >= RELEASE_TIMEOUT) { + push_event(A_RELEASE_TIMEOUT); + emit_current_event(0); + empty_event_sequence(); + } + } + + #if defined(USE_LVP) || defined(USE_THERMAL_REGULATION) + // start a new ADC measurement every 4 ticks + static uint8_t adc_trigger = 0; + adc_trigger ++; + if (adc_trigger > 3) { + adc_trigger = 0; + ADCSRA |= (1 << ADSC) | (1 << ADIE); + } + #endif +} + +#endif -- cgit v1.2.3 From 2ec533abd4592958bef3ec818870e3fb41b64b29 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 28 Sep 2017 17:03:58 -0600 Subject: Added reversing to Anduril. Made EV_tick always send 0 while in "hold" state. Reversing is a build-time option. --- spaghetti-monster/fsm-wdt.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'spaghetti-monster/fsm-wdt.c') diff --git a/spaghetti-monster/fsm-wdt.c b/spaghetti-monster/fsm-wdt.c index afcf467..7cbe0d2 100644 --- a/spaghetti-monster/fsm-wdt.c +++ b/spaghetti-monster/fsm-wdt.c @@ -50,9 +50,6 @@ ISR(WDT_vect) { ticks_since_last_event = (ticks_since_last_event + 1) \ | (ticks_since_last_event & 0x8000); - // callback on each timer tick - emit(EV_tick, ticks_since_last_event); - // if time since last event exceeds timeout, // append timeout to current event sequence, then // send event to current state callback @@ -64,6 +61,14 @@ ISR(WDT_vect) { if (le_num >= 1) last_event = current_event[le_num-1]; if (le_num >= 2) prev_event = current_event[le_num-2]; + // callback on each timer tick + if (last_event == A_HOLD) { + emit(EV_tick, 0); // override tick counter while holding button + } + else { + emit(EV_tick, ticks_since_last_event); + } + // user held button long enough to count as a long click? if (last_event == A_PRESS) { if (ticks_since_last_event >= HOLD_TIMEOUT) { -- cgit v1.2.3 From d50c46d08a6d7f52dffb9b43784c62b11d78df8c Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 11 Dec 2017 19:56:15 -0700 Subject: Greatly improved button debouncing. Helps a lot on FW3A and my light saber. Debouncing isn't 100% yet though. --- spaghetti-monster/fsm-wdt.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) (limited to 'spaghetti-monster/fsm-wdt.c') diff --git a/spaghetti-monster/fsm-wdt.c b/spaghetti-monster/fsm-wdt.c index 7cbe0d2..bee2914 100644 --- a/spaghetti-monster/fsm-wdt.c +++ b/spaghetti-monster/fsm-wdt.c @@ -50,13 +50,42 @@ ISR(WDT_vect) { 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(); - uint8_t last_event = 0; + //uint8_t le_num = last_event_num(); + le_num = last_event_num(); + //uint8_t last_event = 0; + 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]; -- cgit v1.2.3 From 8c13fd82557dadbe81023c534cd19c31ec40bde4 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 12 Dec 2017 15:22:42 -0700 Subject: Debouncing finally works (at least, it does on my two test hosts). --- spaghetti-monster/fsm-wdt.c | 38 +++++++------------------------------- 1 file changed, 7 insertions(+), 31 deletions(-) (limited to 'spaghetti-monster/fsm-wdt.c') 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]; -- cgit v1.2.3 From 30b13cc13baba55ac1610ad471ca737a6c817683 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 24 Jan 2018 18:27:44 -0700 Subject: Work around issues related to ADC interrupt auto-triggering itself. (was firing off 1000 times faster than desired, causing several issues) (now only executes when explicitly requested by the WDT) --- spaghetti-monster/fsm-wdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spaghetti-monster/fsm-wdt.c') diff --git a/spaghetti-monster/fsm-wdt.c b/spaghetti-monster/fsm-wdt.c index 777bef0..ff96ffb 100644 --- a/spaghetti-monster/fsm-wdt.c +++ b/spaghetti-monster/fsm-wdt.c @@ -107,9 +107,9 @@ ISR(WDT_vect) { // start a new ADC measurement every 4 ticks static uint8_t adc_trigger = 0; adc_trigger ++; - if (adc_trigger > 3) { - adc_trigger = 0; + if (0 == (adc_trigger & 3)) { ADCSRA |= (1 << ADSC) | (1 << ADIE); + adcint_enable = 1; } #endif } -- cgit v1.2.3