1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
// tactical-mode.c: Tactical (ish) mode for Anduril.
// Copyright (C) 2023 Selene ToyKeeper
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "tactical-mode.h"
uint8_t tactical_state(Event event, uint16_t arg) {
// momentary(ish) tactical mode
uint8_t mem_lvl = memorized_level; // save this to restore it later
uint8_t ret = EVENT_NOT_HANDLED;
// button is being held
if ((event & (B_CLICK | B_PRESS)) == (B_CLICK | B_PRESS)) {
// 1H: 1st level
// 2H: 2nd level
// 3H: 3rd level
// 4+: nothing
momentary_active = 0;
ret = EVENT_HANDLED;
uint8_t click = event & 0x0f; // click number
if (click <= 3) {
momentary_active = 1;
uint8_t lvl;
lvl = cfg.tactical_levels[click-1];
if ((1 <= lvl) && (lvl <= RAMP_SIZE)) { // steady output
memorized_level = lvl;
momentary_mode = 0;
#if NUM_CHANNEL_MODES > 1
// use ramp mode's channel
channel_mode = cfg.channel_mode;
#endif
} else { // momentary strobe mode
momentary_mode = 1;
if (lvl > RAMP_SIZE) {
current_strobe_type = (lvl - RAMP_SIZE - 1) % strobe_mode_END;
}
}
}
}
// button was released
else if ((event & (B_CLICK | B_PRESS)) == (B_CLICK)) {
momentary_active = 0;
set_level(0);
interrupt_nice_delays(); // stop animations in progress
}
// delegate to momentary mode while button is pressed
if (momentary_active) {
momentary_state(event, arg);
}
memorized_level = mem_lvl; // restore temporarily overridden mem level
// copy lockout mode's aux LED and sleep behaviors
if (event == EV_enter_state) {
lockout_state(event, arg);
}
else if (event == EV_tick) {
if (! momentary_active) {
return lockout_state(event, arg);
}
return EVENT_HANDLED;
}
else if (event == EV_sleep_tick) {
return lockout_state(event, arg);
}
// 6 clicks: exit and turn off
else if (event == EV_6clicks) {
blink_once();
set_state(off_state, 0);
return EVENT_HANDLED;
}
////////// Every action below here is blocked in the simple UI //////////
// (unnecessary since this entire mode is blocked in simple UI)
/*
#ifdef USE_SIMPLE_UI
if (cfg.simple_ui_active) {
return EVENT_NOT_HANDLED;
}
#endif
*/
// 7H: configure tactical mode
else if (event == EV_click7_hold) {
push_state(tactical_config_state, 0);
return EVENT_HANDLED;
}
return ret;
}
void tactical_config_save(uint8_t step, uint8_t value) {
// update tac mode values
// 3 values
// each value is 1 to 150, or other:
// - 1..150 is a ramp level
// - other means "strobe mode"
cfg.tactical_levels[step - 1] = value;
}
uint8_t tactical_config_state(Event event, uint16_t arg) {
return config_state_base(event, arg, 3, tactical_config_save);
}
|