~toykeeper/flashlight-firmware/fsm

« back to all changes in this revision

Viewing changes to ToyKeeper/spaghetti-monster/fsm-misc.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-misc.c: Miscellaneous 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
 
 */
19
 
 
20
 
#ifndef FSM_MISC_C
21
 
#define FSM_MISC_C
22
 
 
 
1
// fsm-misc.c: Miscellaneous function for SpaghettiMonster.
 
2
// Copyright (C) 2017-2023 Selene ToyKeeper
 
3
// SPDX-License-Identifier: GPL-3.0-or-later
 
4
 
 
5
#pragma once
23
6
 
24
7
#ifdef USE_DYNAMIC_UNDERCLOCKING
25
8
void auto_clock_speed() {
47
30
 
48
31
    // "zero" digit gets a single short blink
49
32
    uint8_t ontime = BLINK_SPEED * 2 / 12;
50
 
    if (!num) { ontime = 8; num ++; }
 
33
    if (!num) { ontime = BLINK_ONCE_TIME; num ++; }
 
34
 
 
35
    #ifdef BLINK_CHANNEL
 
36
    // channel is set per blink, to prevent issues
 
37
    // if another mode interrupts us (like a config menu)
 
38
    uint8_t old_channel = channel_mode;
 
39
    #endif
51
40
 
52
41
    for (; num>0; num--) {
 
42
        // TODO: allow setting a blink channel mode per build target
 
43
        #ifdef BLINK_CHANNEL
 
44
            set_channel_mode(BLINK_CHANNEL);
 
45
        #endif
53
46
        set_level(BLINK_BRIGHTNESS);
 
47
        #ifdef BLINK_CHANNEL
 
48
            channel_mode = old_channel;
 
49
        #endif
54
50
        nice_delay_ms(ontime);
 
51
 
 
52
        #ifdef BLINK_CHANNEL
 
53
            set_channel_mode(BLINK_CHANNEL);
 
54
        #endif
55
55
        set_level(0);
 
56
        #ifdef BLINK_CHANNEL
 
57
            channel_mode = old_channel;
 
58
        #endif
56
59
        nice_delay_ms(BLINK_SPEED * 3 / 12);
57
60
    }
 
61
 
 
62
    #ifdef BLINK_CHANNEL
 
63
    set_channel_mode(old_channel);
 
64
    #endif
 
65
 
58
66
    return nice_delay_ms(BLINK_SPEED * 8 / 12);
59
67
}
60
68
#endif
83
91
#endif
84
92
#ifdef USE_BLINK_NUM
85
93
uint8_t blink_num(uint8_t num) {
86
 
    //StatePtr old_state = current_state;
87
 
    #if 0
 
94
    #if 1
88
95
    uint8_t hundreds = num / 100;
89
96
    num = num % 100;
90
97
    uint8_t tens = num / 10;
91
98
    num = num % 10;
92
 
    #else  // 8 bytes smaller
 
99
    #else  // can be smaller or larger, depending on whether divmod is used elsewhere
93
100
    uint8_t hundreds = 0;
94
101
    uint8_t tens = 0;
95
102
    for(; num >= 100; hundreds ++, num -= 100);
102
109
    nice_delay_ms(200);
103
110
    #endif
104
111
 
105
 
    #if 0
106
 
    if (hundreds) {
107
 
        if (! blink_digit(hundreds)) return 0;
108
 
        if (! blink_digit(tens)) return 0;
109
 
    }
110
 
    else if (tens) {
111
 
        if (! blink_digit(tens)) return 0;
112
 
    }
113
 
    if (! blink_digit(num)) return 0;
114
 
    return nice_delay_ms(1000);
115
 
    #else // same size :(
116
 
    if (hundreds) if (! blink_digit(hundreds)) return 0;
117
 
    if (hundreds || tens) if (! blink_digit(tens)) return 0;
118
 
    if (! blink_digit(num)) return 0;
119
 
    return nice_delay_ms(1000);
120
 
    #endif
121
 
 
122
 
    /*
123
 
    uint8_t volts, tenths;
124
 
    volts = voltage / 10;
125
 
    tenths = voltage % 10;
126
 
    if (! blink(volts)) return;
127
 
    nice_delay_ms(200);
128
 
    if (! blink(tenths)) return;
129
 
    nice_delay_ms(200);
130
 
    */
 
112
    if (hundreds) blink_digit(hundreds);
 
113
    if (hundreds || tens) blink_digit(tens);
 
114
    return blink_digit(num);
131
115
}
132
116
#endif
133
117
 
134
118
#ifdef USE_INDICATOR_LED
135
119
void indicator_led(uint8_t lvl) {
136
120
    switch (lvl) {
 
121
        #ifdef AVRXMEGA3  // ATTINY816, 817, etc
 
122
 
 
123
        case 0:  // indicator off
 
124
            AUXLED_PORT.DIRSET = (1 << AUXLED_PIN); // set as output
 
125
            AUXLED_PORT.OUTCLR = (1 << AUXLED_PIN); // set output low
 
126
            #ifdef AUXLED2_PIN  // second LED mirrors the first
 
127
            AUXLED2_PORT.DIRSET = (1 << AUXLED2_PIN); // set as output
 
128
            AUXLED2_PORT.OUTCLR = (1 << AUXLED2_PIN); // set output low
 
129
            #endif
 
130
            break;
 
131
        case 1:  // indicator low
 
132
            AUXLED_PORT.DIRCLR = (1 << AUXLED_PIN); // set as input
 
133
            // this resolves to PORTx.PINxCTRL = PORT_PULLUPEN_bm;
 
134
            *((uint8_t *)&AUXLED_PORT + 0x10 + AUXLED_PIN) = PORT_PULLUPEN_bm; // enable internal pull-up
 
135
            #ifdef AUXLED2_PIN  // second LED mirrors the first
 
136
            AUXLED2_PORT.DIRCLR = (1 << AUXLED2_PIN); // set as input
 
137
            // this resolves to PORTx.PINxCTRL = PORT_PULLUPEN_bm;
 
138
            *((uint8_t *)&AUXLED2_PORT + 0x10 + AUXLED2_PIN) = PORT_PULLUPEN_bm; // enable internal pull-up
 
139
            #endif
 
140
            break;
 
141
        default:  // indicator high
 
142
            AUXLED_PORT.DIRSET = (1 << AUXLED_PIN); // set as output
 
143
            AUXLED_PORT.OUTSET = (1 << AUXLED_PIN); // set as high
 
144
            #ifdef AUXLED2_PIN  // second LED mirrors the first
 
145
            AUXLED2_PORT.DIRSET = (1 << AUXLED2_PIN); // set as output
 
146
            AUXLED2_PORT.OUTSET = (1 << AUXLED2_PIN); // set as high
 
147
            #endif
 
148
            break;
 
149
 
 
150
        #else  // MCU is old tiny style, not newer mega style
 
151
 
137
152
        case 0:  // indicator off
138
153
            DDRB &= 0xff ^ (1 << AUXLED_PIN);
139
154
            PORTB &= 0xff ^ (1 << AUXLED_PIN);
158
173
            PORTB |= (1 << AUXLED2_PIN);
159
174
            #endif
160
175
            break;
 
176
 
 
177
        #endif  // MCU type
161
178
    }
162
179
}
163
180
 
174
191
// TODO: Refactor this and RGB LED function to merge code and save space
175
192
void button_led_set(uint8_t lvl) {
176
193
    switch (lvl) {
 
194
 
 
195
        #ifdef AVRXMEGA3  // ATTINY816, 817, etc
 
196
 
 
197
        case 0:  // LED off
 
198
            BUTTON_LED_PORT.DIRSET = (1 << BUTTON_LED_PIN); // set as output
 
199
            BUTTON_LED_PORT.OUTCLR = (1 << BUTTON_LED_PIN); // set output low
 
200
            break;
 
201
        case 1:  // LED low
 
202
            BUTTON_LED_PORT.DIRCLR = (1 << BUTTON_LED_PIN); // set as input
 
203
            // this resolves to PORTx.PINxCTRL = PORT_PULLUPEN_bm;
 
204
            *((uint8_t *)&BUTTON_LED_PORT + 0x10 + BUTTON_LED_PIN) = PORT_PULLUPEN_bm; // enable internal pull-up
 
205
            break;
 
206
        default:  // LED high
 
207
            BUTTON_LED_PORT.DIRSET = (1 << BUTTON_LED_PIN); // set as output
 
208
            BUTTON_LED_PORT.OUTSET = (1 << BUTTON_LED_PIN); // set as high
 
209
            break;
 
210
 
 
211
        #else
 
212
 
177
213
        case 0:  // LED off
178
214
            BUTTON_LED_DDR  &= 0xff ^ (1 << BUTTON_LED_PIN);
179
215
            BUTTON_LED_PUE  &= 0xff ^ (1 << BUTTON_LED_PIN);
189
225
            BUTTON_LED_PUE  |= (1 << BUTTON_LED_PIN);
190
226
            BUTTON_LED_PORT |= (1 << BUTTON_LED_PIN);
191
227
            break;
 
228
 
 
229
        #endif  // MCU type
192
230
    }
193
231
}
194
232
#endif
201
239
        uint8_t lvl = (value >> (i<<1)) & 0x03;
202
240
        uint8_t pin = pins[i];
203
241
        switch (lvl) {
 
242
 
 
243
            #ifdef AVRXMEGA3  // ATTINY816, 817, etc
 
244
 
 
245
            case 0:  // LED off
 
246
                AUXLED_RGB_PORT.DIRSET = (1 << pin); // set as output
 
247
                AUXLED_RGB_PORT.OUTCLR = (1 << pin); // set output low
 
248
                break;
 
249
            case 1:  // LED low
 
250
                AUXLED_RGB_PORT.DIRCLR = (1 << pin); // set as input
 
251
                // this resolves to PORTx.PINxCTRL = PORT_PULLUPEN_bm;
 
252
                *((uint8_t *)&AUXLED_RGB_PORT + 0x10 + pin) = PORT_PULLUPEN_bm; // enable internal pull-up
 
253
                break;
 
254
            default:  // LED high
 
255
                AUXLED_RGB_PORT.DIRSET = (1 << pin); // set as output
 
256
                AUXLED_RGB_PORT.OUTSET = (1 << pin); // set as high
 
257
                break;
 
258
 
 
259
            #else
 
260
 
204
261
            case 0:  // LED off
205
262
                AUXLED_RGB_DDR  &= 0xff ^ (1 << pin);
206
263
                AUXLED_RGB_PUE  &= 0xff ^ (1 << pin);
216
273
                AUXLED_RGB_PUE  |= (1 << pin);
217
274
                AUXLED_RGB_PORT |= (1 << pin);
218
275
                break;
 
276
 
 
277
            #endif  // MCU type
219
278
        }
220
279
    }
221
280
}
241
300
        // reset (WDIF + WDE), no WDIE, fastest (16ms) timing (0000)
242
301
        // (DS section 8.5.2 and table 8-4)
243
302
        WDTCSR = 0b10001000;
 
303
    #elif defined(AVRXMEGA3)  // ATTINY816, 817, etc
 
304
        CCP = CCP_IOREG_gc;  // temporarily disable change protection
 
305
        WDT.CTRLA = WDT_PERIOD_8CLK_gc;  // Enable, timeout 8ms
244
306
    #endif
245
307
    sei();
246
308
    wdt_reset();
248
310
}
249
311
#endif
250
312
 
251
 
#endif