/* * fsm-events.c: Event-handling 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_EVENTS_C #define FSM_EVENTS_C void empty_event_sequence() { current_event = EV_none; // when the user completes an input sequence, interrupt any running timers // to cancel any delays currently in progress // This eliminates a whole bunch of extra code: // before: if (! nice_delay_ms(ms)) {break;} // after: nice_delay_ms(ms); interrupt_nice_delays(); } uint8_t push_event(uint8_t ev_type) { ticks_since_last_event = 0; // something happened // only click events are sent to this function current_event |= B_CLICK; // handle button presses if (ev_type == B_PRESS) { // set press flag current_event |= B_PRESS; // increase click counter if ((current_event & B_COUNT) < (B_COUNT-1)) { current_event ++; } return 1; // event pushed, even if max clicks already reached // (will just repeat the max over and over) } // handle button releases else if (ev_type == B_RELEASE) { // clear the press flag current_event &= (~B_PRESS); // if a "hold" event just ended, set the timeout flag // to indicate that the event is done and can be cleared if (current_event & B_HOLD) { current_event |= B_TIMEOUT; } return 1; // event pushed } return 0; // unexpected event type } void append_emission(Event event, uint16_t arg) { uint8_t i; // find last entry for(i=0; (i 0) { #ifdef USE_DYNAMIC_UNDERCLOCKING #ifdef USE_RAMPING uint8_t level = actual_level; // volatile, avoid repeat access if (level < QUARTERSPEED_LEVEL) { CLKPR = 1< 0) { // underclock MCU to save power CLKPR = 1<=0; i--) { uint8_t err = state_stack[i](event, arg); if (! err) return 0; } return 1; // event not handled } void emit(Event event, uint16_t arg) { // add this event to the queue for later, // so we won't use too much time during an interrupt append_emission(event, arg); } void emit_current_event(uint16_t arg) { ticks_since_last_event = arg; emit(current_event, arg); } #endif