~toykeeper/flashlight-firmware/fsm

« back to all changes in this revision

Viewing changes to ToyKeeper/spaghetti-monster/anduril/lockout-mode.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
// lockout-mode.c: Lockout mode for Anduril.
 
2
// Copyright (C) 2017-2023 Selene ToyKeeper
 
3
// SPDX-License-Identifier: GPL-3.0-or-later
 
4
 
 
5
#pragma once
 
6
 
 
7
#include "lockout-mode.h"
 
8
 
 
9
uint8_t lockout_state(Event event, uint16_t arg) {
 
10
    #ifdef USE_MOON_DURING_LOCKOUT_MODE
 
11
    // momentary(ish) moon mode during lockout
 
12
    // button is being held
 
13
    #ifdef USE_AUX_RGB_LEDS
 
14
    // don't turn on during RGB aux LED configuration
 
15
    if (event == EV_click7_hold) { set_level(0); } else
 
16
    #endif
 
17
    if ((event & (B_CLICK | B_PRESS)) == (B_CLICK | B_PRESS)) {
 
18
        // hold: lowest floor
 
19
        // click, hold: highest floor (or manual mem level)
 
20
        uint8_t lvl = cfg.ramp_floors[0];
 
21
        if (1 == (event & 0x0f)) {  // first click
 
22
            if (cfg.ramp_floors[1] < lvl) lvl = cfg.ramp_floors[1];
 
23
        } else {  // 2nd click or later
 
24
            if (cfg.ramp_floors[1] > lvl) lvl = cfg.ramp_floors[1];
 
25
            #ifdef USE_MANUAL_MEMORY
 
26
            if (cfg.manual_memory) lvl = cfg.manual_memory;
 
27
            #endif
 
28
        }
 
29
        set_level(lvl);
 
30
    }
 
31
    // button was released
 
32
    else if ((event & (B_CLICK | B_PRESS)) == (B_CLICK)) {
 
33
        set_level(0);
 
34
    }
 
35
    #endif  // ifdef USE_MOON_DURING_LOCKOUT_MODE
 
36
 
 
37
    // regular event handling
 
38
    // conserve power while locked out
 
39
    // (allow staying awake long enough to exit, but otherwise
 
40
    //  be persistent about going back to sleep every few seconds
 
41
    //  even if the user keeps pressing the button)
 
42
    if (event == EV_enter_state) {
 
43
        ticks_since_on = 0;
 
44
        #ifdef USE_INDICATOR_LED
 
45
            // redundant, sleep tick does the same thing
 
46
            // indicator_led_update(cfg.indicator_led_mode >> 2, 0);
 
47
        #elif defined(USE_AUX_RGB_LEDS)
 
48
            rgb_led_update(cfg.rgb_led_lockout_mode, 0);
 
49
        #endif
 
50
    }
 
51
 
 
52
    else if (event == EV_tick) {
 
53
        if (arg > HOLD_TIMEOUT) {
 
54
            go_to_standby = 1;
 
55
            #ifdef USE_INDICATOR_LED
 
56
            // redundant, sleep tick does the same thing
 
57
            //indicator_led_update(cfg.indicator_led_mode >> 2, arg);
 
58
            #elif defined(USE_AUX_RGB_LEDS)
 
59
            rgb_led_update(cfg.rgb_led_lockout_mode, arg);
 
60
            #endif
 
61
        }
 
62
        return EVENT_HANDLED;
 
63
    }
 
64
 
 
65
    #if defined(TICK_DURING_STANDBY) && (defined(USE_INDICATOR_LED) || defined(USE_AUX_RGB_LEDS))
 
66
    else if (event == EV_sleep_tick) {
 
67
        if (ticks_since_on < 255) ticks_since_on ++;
 
68
        #ifdef USE_MANUAL_MEMORY_TIMER
 
69
        // reset to manual memory level when timer expires
 
70
        if (cfg.manual_memory &&
 
71
                (arg >= (cfg.manual_memory_timer * SLEEP_TICKS_PER_MINUTE))) {
 
72
            manual_memory_restore();
 
73
        }
 
74
        #endif
 
75
        #if defined(USE_INDICATOR_LED)
 
76
        indicator_led_update(cfg.indicator_led_mode >> 2, arg);
 
77
        #elif defined(USE_AUX_RGB_LEDS)
 
78
        rgb_led_update(cfg.rgb_led_lockout_mode, arg);
 
79
        #endif
 
80
        return EVENT_HANDLED;
 
81
    }
 
82
    #endif
 
83
 
 
84
    // 3 clicks: exit and turn off
 
85
    else if (event == EV_3clicks) {
 
86
        blink_once();
 
87
        set_state(off_state, 0);
 
88
        return EVENT_HANDLED;
 
89
    }
 
90
 
 
91
    // 4 clicks: exit and turn on
 
92
    else if (event == EV_4clicks) {
 
93
        #if defined(USE_MANUAL_MEMORY) && !defined(USE_MANUAL_MEMORY_TIMER)
 
94
        // this clause probably isn't used by any configs any more
 
95
        // but is included just in case someone configures it this way
 
96
        if (cfg.manual_memory)
 
97
            set_state(steady_state, cfg.manual_memory);
 
98
        else
 
99
        #endif
 
100
        set_state(steady_state, memorized_level);
 
101
        return EVENT_HANDLED;
 
102
    }
 
103
 
 
104
    // 4 clicks, but hold last: exit and start at floor
 
105
    else if (event == EV_click4_hold) {
 
106
        //blink_once();
 
107
        blip();
 
108
        // reset button sequence to avoid activating anything in ramp mode
 
109
        current_event = 0;
 
110
        // ... and back to ramp mode
 
111
        set_state(steady_state, 1);
 
112
        return EVENT_HANDLED;
 
113
    }
 
114
 
 
115
    // 5 clicks: exit and turn on at ceiling level
 
116
    else if (event == EV_5clicks) {
 
117
        set_state(steady_state, MAX_LEVEL);
 
118
        return EVENT_HANDLED;
 
119
    }
 
120
 
 
121
    #if NUM_CHANNEL_MODES > 1
 
122
    // 3H: next channel mode
 
123
    else if (event == EV_click3_hold) {
 
124
        if (0 == (arg % TICKS_PER_SECOND)) {
 
125
            // pretend the user clicked 3 times to change channels
 
126
            return channel_mode_state(EV_3clicks, 0);
 
127
        }
 
128
    }
 
129
    #endif
 
130
 
 
131
    ////////// Every action below here is blocked in the (non-Extended) Simple UI //////////
 
132
 
 
133
    #if defined(USE_SIMPLE_UI) && !defined(USE_EXTENDED_SIMPLE_UI)
 
134
    if (cfg.simple_ui_active) {
 
135
        return EVENT_NOT_HANDLED;
 
136
    }
 
137
    #endif  // if simple UI but not extended simple UI
 
138
 
 
139
    #if defined(USE_INDICATOR_LED)
 
140
    // 7 clicks: rotate through indicator LED modes (lockout mode)
 
141
    else if (event == EV_7clicks) {
 
142
        #if defined(USE_INDICATOR_LED)
 
143
            uint8_t mode = cfg.indicator_led_mode >> 2;
 
144
            #ifdef TICK_DURING_STANDBY
 
145
            mode = (mode + 1) & 3;
 
146
            #else
 
147
            mode = (mode + 1) % 3;
 
148
            #endif
 
149
            #ifdef INDICATOR_LED_SKIP_LOW
 
150
            if (mode == 1) { mode ++; }
 
151
            #endif
 
152
            cfg.indicator_led_mode = (mode << 2) + (cfg.indicator_led_mode & 0x03);
 
153
            // redundant, sleep tick does the same thing
 
154
            //indicator_led_update(cfg.indicator_led_mode >> 2, arg);
 
155
        #elif defined(USE_AUX_RGB_LEDS)
 
156
        #endif
 
157
        save_config();
 
158
        return EVENT_HANDLED;
 
159
    }
 
160
    #elif defined(USE_AUX_RGB_LEDS)
 
161
    // 7 clicks: change RGB aux LED pattern
 
162
    else if (event == EV_7clicks) {
 
163
        uint8_t mode = (cfg.rgb_led_lockout_mode >> 4) + 1;
 
164
        mode = mode % RGB_LED_NUM_PATTERNS;
 
165
        cfg.rgb_led_lockout_mode = (mode << 4) | (cfg.rgb_led_lockout_mode & 0x0f);
 
166
        rgb_led_update(cfg.rgb_led_lockout_mode, 0);
 
167
        save_config();
 
168
        blink_once();
 
169
        return EVENT_HANDLED;
 
170
    }
 
171
    // 7H: change RGB aux LED color
 
172
    else if (event == EV_click7_hold) {
 
173
        setting_rgb_mode_now = 1;
 
174
        if (0 == (arg & 0x3f)) {
 
175
            uint8_t mode = (cfg.rgb_led_lockout_mode & 0x0f) + 1;
 
176
            mode = mode % RGB_LED_NUM_COLORS;
 
177
            cfg.rgb_led_lockout_mode = mode | (cfg.rgb_led_lockout_mode & 0xf0);
 
178
            //save_config();
 
179
        }
 
180
        rgb_led_update(cfg.rgb_led_lockout_mode, arg);
 
181
        return EVENT_HANDLED;
 
182
    }
 
183
    // 7H, release: save new color
 
184
    else if (event == EV_click7_hold_release) {
 
185
        setting_rgb_mode_now = 0;
 
186
        save_config();
 
187
        return EVENT_HANDLED;
 
188
    }
 
189
    #endif
 
190
 
 
191
    #if defined(USE_EXTENDED_SIMPLE_UI) && defined(USE_SIMPLE_UI)
 
192
    ////////// Every action below here is blocked in the Extended Simple UI //////////
 
193
    if (cfg.simple_ui_active) {
 
194
        return EVENT_NOT_HANDLED;
 
195
    }
 
196
    #endif  // if extended simple UI
 
197
 
 
198
    #ifdef USE_AUTOLOCK
 
199
    // 10H: configure the autolock option
 
200
    else if (event == EV_click10_hold) {
 
201
        push_state(autolock_config_state, 0);
 
202
        return EVENT_HANDLED;
 
203
    }
 
204
    #endif
 
205
 
 
206
    return EVENT_NOT_HANDLED;
 
207
}
 
208
 
 
209
#ifdef USE_AUTOLOCK
 
210
// set the auto-lock timer to N minutes, where N is the number of clicks
 
211
void autolock_config_save(uint8_t step, uint8_t value) {
 
212
    cfg.autolock_time = value;
 
213
}
 
214
 
 
215
uint8_t autolock_config_state(Event event, uint16_t arg) {
 
216
    return config_state_base(event, arg, 1, autolock_config_save);
 
217
}
 
218
#endif  // #ifdef USE_AUTOLOCK
 
219