2
* fsm-wdt.c: WDT (Watch Dog Timer) functions for SpaghettiMonster.
4
* Copyright (C) 2017 Selene Scriven
6
* This program is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation, either version 3 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1
// fsm-wdt.c: WDT (Watch Dog Timer) functions for SpaghettiMonster.
2
// Copyright (C) 2017-2023 Selene ToyKeeper
3
// SPDX-License-Identifier: GPL-3.0-or-later
23
7
#include <avr/interrupt.h>
24
8
#include <avr/wdt.h>
10
// *** Note for the AVRXMEGA3 (1-Series, eg 816 and 817), the WDT
11
// is not used for time-based interrupts. A new peripheral, the
12
// Periodic Interrupt Timer ("PIT") is used for this purpose.
28
16
#if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85)
35
23
#elif (ATTINY == 1634)
36
24
wdt_reset(); // Reset the WDT
37
25
WDTCSR = (1<<WDIE); // Enable interrupt every 16ms
26
#elif defined(AVRXMEGA3) // ATTINY816, 817, etc
27
RTC.PITINTCTRL = RTC_PI_bm; // enable the Periodic Interrupt
28
while (RTC.PITSTATUS > 0) {} // make sure the register is ready to be updated
29
RTC.PITCTRLA = RTC_PERIOD_CYC512_gc | RTC_PITEN_bm; // Period = 16ms, enable the PI Timer
39
31
#error Unrecognized MCU type
53
45
#elif (ATTINY == 1634)
54
46
wdt_reset(); // Reset the WDT
55
47
WDTCSR = (1<<WDIE) | STANDBY_TICK_SPEED;
48
#elif defined(AVRXMEGA3) // ATTINY816, 817, etc
49
RTC.PITINTCTRL = RTC_PI_bm; // enable the Periodic Interrupt
50
while (RTC.PITSTATUS > 0) {} // make sure the register is ready to be updated
51
RTC.PITCTRLA = (1<<6) | (STANDBY_TICK_SPEED<<3) | RTC_PITEN_bm; // Set period, enable the PI Timer
57
53
#error Unrecognized MCU type
75
71
CCP = 0xD8; // enable config changes
76
72
WDTCSR = 0; // disable and clear all WDT settings
74
#elif defined(AVRXMEGA3) // ATTINY816, 817, etc
75
while (RTC.PITSTATUS > 0) {} // make sure the register is ready to be updated
76
RTC.PITCTRLA = 0; // Disable the PI Timer
79
78
#error Unrecognized MCU type
83
82
// clock tick -- this runs every 16ms (62.5 fps)
83
#ifdef AVRXMEGA3 // ATTINY816, 817, etc
85
RTC.PITINTFLAGS = RTC_PI_bm; // clear the PIT interrupt flag
85
89
irq_wdt = 1; // WDT event happened
118
122
#ifndef USE_SLEEP_LVP
119
123
return; // no sleep LVP needed if nothing drains power while off
121
// stop here, usually... but proceed often enough for sleep LVP to work
122
if (0 != (ticks_since_last & 0x3f)) return;
125
// stop here, usually... except during the first few seconds asleep,
126
// and once in a while afterward for sleep LVP
127
if ((ticks_since_last > (8 * SLEEP_TICKS_PER_SECOND))
128
&& (0 != (ticks_since_last & 0x0f))) return;
124
130
adc_trigger = 0; // make sure a measurement will happen
131
adc_active_now = 1; // use ADC noise reduction sleep mode
125
132
ADC_on(); // enable ADC voltage measurement functions temporarily
160
168
else if (current_event) {
161
169
// "hold" event just ended
162
170
// no timeout required when releasing a long-press
163
// TODO? move this logic to PCINT() and simplify things here?
164
171
if (current_event & B_HOLD) {
165
//emit_current_event(0); // should have been emitted by PCINT_inner()
172
//emit_current_event(ticks_since_last); // should have been emitted by PCINT_inner()
166
173
empty_event_sequence();
168
175
// end and clear event after release timeout