~toykeeper/flashlight-firmware/fsm

« back to all changes in this revision

Viewing changes to ToyKeeper/spaghetti-monster/fsm-main.c

  • Committer: Selene ToyKeeper
  • Date: 2023-11-04 15:09:10 UTC
  • mfrom: (483.1.175 anduril2)
  • Revision ID: bzr@toykeeper.net-20231104150910-ddd3afw4nhfvof2l
merged anduril2 branch -> fsm, with *years* of changes
(this also means this code is now Anduril 2 instead of Anduril 1)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * fsm-main.c: main() function for SpaghettiMonster.
3
 
 *
4
 
 * Copyright (C) 2017 Selene Scriven
5
 
 *
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.
10
 
 *
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.
15
 
 *
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/>.
18
 
 */
 
1
// fsm-main.c: main() function for SpaghettiMonster.
 
2
// Copyright (C) 2017-2023 Selene ToyKeeper
 
3
// SPDX-License-Identifier: GPL-3.0-or-later
19
4
 
20
 
#ifndef FSM_MAIN_C
21
 
#define FSM_MAIN_C
 
5
#pragma once
22
6
 
23
7
#include "fsm-main.h"
24
8
 
25
9
#if PWM_CHANNELS == 4
 
10
#ifdef AVRXMEGA3  // ATTINY816, 817, etc
 
11
#error 4-channel PWM not currently set up for the AVR 1-Series
 
12
#endif
26
13
// 4th PWM channel requires manually turning the pin on/off via interrupt :(
27
14
ISR(TIMER1_OVF_vect) {
28
15
    //bitClear(PORTB, 3);
36
23
}
37
24
#endif
38
25
 
 
26
// FIXME: hw_setup() shouldn't be here ... move it entirely to hwdef files
39
27
#if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85)
40
28
static inline void hw_setup() {
41
 
    // configure PWM channels
42
 
    #if PWM_CHANNELS >= 1
43
 
    DDRB |= (1 << PWM1_PIN);
44
 
    TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)
45
 
    TCCR0A = PHASE;
46
 
    #endif
47
 
    #if PWM_CHANNELS >= 2
48
 
    DDRB |= (1 << PWM2_PIN);
49
 
    #endif
50
 
    #if PWM_CHANNELS >= 3
51
 
    // Second PWM counter is ... weird
52
 
    DDRB |= (1 << PWM3_PIN);
53
 
    TCCR1 = _BV (CS10);
54
 
    GTCCR = _BV (COM1B1) | _BV (PWM1B);
55
 
    OCR1C = 255;  // Set ceiling value to maximum
56
 
    #endif
57
 
    #if PWM_CHANNELS >= 4
58
 
    // 4th PWM channel is ... not actually supported in hardware  :(
59
 
    DDRB |= (1 << PWM4_PIN);
60
 
    //OCR1C = 255;  // Set ceiling value to maximum
61
 
    TCCR1 = 1<<CTC1 | 1<<PWM1A | 3<<COM1A0 | 2<<CS10;
62
 
    GTCCR = (2<<COM1B0) | (1<<PWM1B);
63
 
    // set up an interrupt to control PWM4 pin
64
 
    TIMSK |= (1<<OCIE1A) | (1<<TOIE1);
65
 
    #endif
 
29
    #if !defined(USE_GENERIC_HWDEF_SETUP)
 
30
        hwdef_setup();
 
31
    #else
 
32
        // configure PWM channels
 
33
        #if PWM_CHANNELS >= 1
 
34
            DDRB |= (1 << PWM1_PIN);
 
35
            TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)
 
36
            TCCR0A = PHASE;
 
37
            #if (PWM1_PIN == PB4) // Second PWM counter is ... weird
 
38
                TCCR1 = _BV (CS10);
 
39
                GTCCR = _BV (COM1B1) | _BV (PWM1B);
 
40
                OCR1C = 255;  // Set ceiling value to maximum
 
41
            #endif
 
42
        #endif
 
43
        // tint ramping needs second channel enabled,
 
44
        // despite PWM_CHANNELS being only 1
 
45
        #if (PWM_CHANNELS >= 2) || defined(USE_TINT_RAMPING)
 
46
            DDRB |= (1 << PWM2_PIN);
 
47
            #if (PWM2_PIN == PB4) // Second PWM counter is ... weird
 
48
                TCCR1 = _BV (CS10);
 
49
                GTCCR = _BV (COM1B1) | _BV (PWM1B);
 
50
                OCR1C = 255;  // Set ceiling value to maximum
 
51
            #endif
 
52
        #endif
 
53
        #if PWM_CHANNELS >= 3
 
54
            DDRB |= (1 << PWM3_PIN);
 
55
            #if (PWM3_PIN == PB4) // Second PWM counter is ... weird
 
56
                TCCR1 = _BV (CS10);
 
57
                GTCCR = _BV (COM1B1) | _BV (PWM1B);
 
58
                OCR1C = 255;  // Set ceiling value to maximum
 
59
            #endif
 
60
        #endif
 
61
        #if PWM_CHANNELS >= 4
 
62
            // 4th PWM channel is ... not actually supported in hardware  :(
 
63
            DDRB |= (1 << PWM4_PIN);
 
64
            //OCR1C = 255;  // Set ceiling value to maximum
 
65
            TCCR1 = 1<<CTC1 | 1<<PWM1A | 3<<COM1A0 | 2<<CS10;
 
66
            GTCCR = (2<<COM1B0) | (1<<PWM1B);
 
67
            // set up an interrupt to control PWM4 pin
 
68
            TIMSK |= (1<<OCIE1A) | (1<<TOIE1);
 
69
        #endif
66
70
 
67
 
    // configure e-switch
68
 
    PORTB = (1 << SWITCH_PIN);  // e-switch is the only input
69
 
    PCMSK = (1 << SWITCH_PIN);  // pin change interrupt uses this pin
 
71
        // configure e-switch
 
72
        PORTB = (1 << SWITCH_PIN);  // e-switch is the only input
 
73
        PCMSK = (1 << SWITCH_PIN);  // pin change interrupt uses this pin
 
74
    #endif  // ifdef USE_GENERIC_HWDEF_SETUP
70
75
}
71
 
#elif (ATTINY == 1634)
 
76
#elif (ATTINY == 1634) || defined(AVRXMEGA3)  // ATTINY816, 817, etc
72
77
static inline void hw_setup() {
73
78
    // this gets tricky with so many pins...
74
79
    // ... so punt it to the hwdef file
82
87
//#ifdef USE_REBOOT
83
88
static inline void prevent_reboot_loop() {
84
89
    // prevent WDT from rebooting MCU again
 
90
    #ifdef AVRXMEGA3  // ATTINY816, 817, etc
 
91
    RSTCTRL.RSTFR &= ~(RSTCTRL_WDRF_bm);  // reset status flag
 
92
    #else
85
93
    MCUSR &= ~(1<<WDRF);  // reset status flag
 
94
    #endif
86
95
    wdt_disable();
87
96
}
88
97
//#endif
129
138
    // fallback for handling a few things
130
139
    #ifndef DONT_USE_DEFAULT_STATE
131
140
    push_state(default_state, 0);
 
141
    nice_delay_interrupt = 0;
132
142
    #endif
133
143
 
134
144
    // call recipe's setup
139
149
        // if event queue not empty, empty it
140
150
        process_emissions();
141
151
 
 
152
        // if loop() tried to change state, process that now
 
153
        StatePtr df = deferred_state;
 
154
        if (df) {
 
155
            set_state(df, deferred_state_arg);
 
156
            deferred_state = NULL;
 
157
            //deferred_state_arg = 0;  // unnecessary
 
158
        }
 
159
 
142
160
        // enter standby mode if requested
143
161
        // (works better if deferred like this)
144
162
        if (go_to_standby) {
164
182
        // catch up on interrupts
165
183
        handle_deferred_interrupts();
166
184
 
 
185
        // turn delays back on, if they were off
 
186
        nice_delay_interrupt = 0;
 
187
 
167
188
        // give the recipe some time slices
168
189
        loop();
169
190
 
170
 
        // in case we fell through, turn delays back on
171
 
        nice_delay_interrupt = 0;
172
191
    }
173
192
}
174
193
 
190
209
    }
191
210
}
192
211
 
193
 
#endif