aboutsummaryrefslogtreecommitdiff
path: root/fsm/pcint.c
diff options
context:
space:
mode:
authorSelene ToyKeeper2023-11-02 17:16:25 -0600
committerSelene ToyKeeper2023-11-02 17:16:25 -0600
commit7cb4fe0944b839f28dfd96a88a772cd6a8b58019 (patch)
tree8d3b203f1650edc28b1f67e1589e3bc870b33fa6 /fsm/pcint.c
parentadded LICENSE (GPLv3) (diff)
downloadanduril-7cb4fe0944b839f28dfd96a88a772cd6a8b58019.tar.gz
anduril-7cb4fe0944b839f28dfd96a88a772cd6a8b58019.tar.bz2
anduril-7cb4fe0944b839f28dfd96a88a772cd6a8b58019.zip
reorganized project files (part 1)
(just moved files, didn't change the contents yet, and nothing will work without updating #includes and build scripts and stuff)
Diffstat (limited to 'fsm/pcint.c')
-rw-r--r--fsm/pcint.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/fsm/pcint.c b/fsm/pcint.c
new file mode 100644
index 0000000..131d0c3
--- /dev/null
+++ b/fsm/pcint.c
@@ -0,0 +1,96 @@
+// fsm-pcint.c: PCINT (Pin Change Interrupt) functions for SpaghettiMonster.
+// Copyright (C) 2017-2023 Selene ToyKeeper
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include <avr/interrupt.h>
+#include <util/delay_basic.h>
+
+uint8_t button_is_pressed() {
+ uint8_t value = ((SWITCH_PORT & (1<<SWITCH_PIN)) == 0);
+ button_last_state = value;
+ return value;
+}
+
+inline void PCINT_on() {
+ #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85)
+ // enable pin change interrupt
+ GIMSK |= (1 << PCIE);
+ // only pay attention to the e-switch pin
+ #if 0 // this is redundant; was already done in main()
+ PCMSK = (1 << SWITCH_PCINT);
+ #endif
+ // set bits 1:0 to 0b01 (interrupt on rising *and* falling edge) (default)
+ // MCUCR &= 0b11111101; MCUCR |= 0b00000001;
+ #elif (ATTINY == 1634)
+ // enable pin change interrupt
+ #ifdef SWITCH2_PCIE
+ GIMSK |= ((1 << SWITCH_PCIE) | (1 << SWITCH2_PCIE));
+ #else
+ GIMSK |= (1 << SWITCH_PCIE);
+ #endif
+ #elif defined(AVRXMEGA3) // ATTINY816, 817, etc)
+ SWITCH_ISC_REG |= PORT_ISC_BOTHEDGES_gc;
+ #else
+ #error Unrecognized MCU type
+ #endif
+}
+
+inline void PCINT_off() {
+ #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85)
+ // disable all pin-change interrupts
+ GIMSK &= ~(1 << PCIE);
+ #elif (ATTINY == 1634)
+ // disable all pin-change interrupts
+ GIMSK &= ~(1 << SWITCH_PCIE);
+ #elif defined(AVRXMEGA3) // ATTINY816, 817, etc)
+ SWITCH_ISC_REG &= ~(PORT_ISC_gm);
+ #else
+ #error Unrecognized MCU type
+ #endif
+}
+
+//void button_change_interrupt() {
+#if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) || (ATTINY == 1634)
+ #ifdef PCINT_vect
+ ISR(PCINT_vect) {
+ #else
+ ISR(PCINT0_vect) {
+ #endif
+#elif defined(AVRXMEGA3) // ATTINY816, 817, etc)
+ ISR(SWITCH_VECT) {
+ // Write a '1' to clear the interrupt flag
+ SWITCH_INTFLG |= (1 << SWITCH_PIN);
+#else
+ #error Unrecognized MCU type
+#endif
+
+ irq_pcint = 1; // let deferred code know an interrupt happened
+
+ //DEBUG_FLASH;
+
+ // 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());
+}
+
+// should only be called from PCINT and/or WDT
+// (is a separate function to reduce code duplication)
+void PCINT_inner(uint8_t pressed) {
+ button_last_state = pressed;
+
+ // register the change, and send event to the current state callback
+ if (pressed) { // user pressed button
+ push_event(B_PRESS);
+ emit_current_event(0);
+ } else { // user released button
+ // how long was the button held?
+ push_event(B_RELEASE);
+ emit_current_event(ticks_since_last_event);
+ }
+ ticks_since_last_event = 0;
+}
+