-
Notifications
You must be signed in to change notification settings - Fork 92
/
Copy pathsettings_menu_example.py
200 lines (179 loc) · 8.3 KB
/
settings_menu_example.py
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# Copyright 2024 Allen Synthesis
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
This is an example of how to use the SettingsMenu class.
It is not intended to be a useful script, just a convenient programming
reference to show how the menu system _can_ be used.
"""
from configuration import *
from europi import *
from europi_script import EuroPiScript
from experimental.settings_menu import *
class SettingsMenuExample(EuroPiScript):
def __init__(self):
super().__init__()
on_off_labels = {
True: "On",
False: "Off"
}
# Create the main menu
# the menu items can be generated ad-hoc like this, or passed
# as an array generated elsewhere
self.menu = SettingsMenu(
menu_items = [
SettingMenuItem(
config_point = FloatConfigPoint(
name="cv1_volts", # every config point must have a unique name!
minimum=0.0,
maximum=europi_config.MAX_OUTPUT_VOLTAGE,
default=0.0,
),
prefix="Analog",
title="CV1",
# This is a function that gets called when the user changes the setting
# callback_arg is an additional parameter we can pass to the callback
# Note: we don't NEED to use a callback; we can just read the ConfigPoint
# in the main loop and apply it there if desired.
#
# The callback is executed inside the button-handler interrupt routine,
# so any CPU-intensive or interrupt-blocking behaviour (e.g. disk IO to save
# a file, or rendering the display) should NOT be done via a callback function.
callback=self.set_analog_cv,
callback_arg=cv1,
# change this to increase the resolution of floats
# making it too large may cause issues with flickering
# generally 1-2 should be fine, 3 is usable for relatively
# small ranges (e.g. 0-1 with 3 decimal places)
float_resolution=1,
# For this channel only, let's also enable AIN and K1 to be used
# to control the voltage on CV1
# When the user selects "Knob" or "AIN" as the value for this channel
# the menu will read the value of K1/AIN and use that to choose
# between the manually-selectable options at a rate of 10Hz
autoselect_knob=True,
autoselect_cv=True,
# Create child items that can be accessed with a long-press
children=[
SettingMenuItem(
config_point=FloatConfigPoint(
name="cv2_volts",
minimum=0.0,
maximum=europi_config.MAX_OUTPUT_VOLTAGE,
default=0.0,
),
prefix="Analog",
title="CV2",
callback=self.set_analog_cv,
callback_arg=cv2,
float_resolution=1,
),
SettingMenuItem(
config_point=FloatConfigPoint(
name="cv3_volts",
minimum=0.0,
maximum=europi_config.MAX_OUTPUT_VOLTAGE,
default=0.0,
),
prefix="Analog",
title="CV3",
callback=self.set_analog_cv,
callback_arg=cv3,
float_resolution=1,
),
]
),
SettingMenuItem(
config_point = BooleanConfigPoint(
name="cv4_on",
default=False,
),
prefix="Digital",
title="CV4",
callback=self.set_digital_cv,
callback_arg=cv4,
labels=on_off_labels,
children=[
SettingMenuItem(
config_point=BooleanConfigPoint(
name="cv5_on",
default=False,
),
prefix="Digital",
title="CV5",
callback=self.set_digital_cv,
callback_arg=cv5,
labels=on_off_labels,
),
SettingMenuItem(
config_point=BooleanConfigPoint(
name="cv6_on",
default=False,
),
prefix="Digital",
title="CV6",
callback=self.set_digital_cv,
callback_arg=cv6,
labels=on_off_labels,
),
]
),
]
)
# Read the persistent settings file and load the settings for the menu's configuration points
# This will trigger the callbacks as necessary
# The _state_filename property is defined in EuroPiScript.
self.menu.load_defaults(self._state_filename)
def set_analog_cv(self, new_value, old_value, config_point, arg=None):
"""
Callback function for the CV1-3 menu items
These are floating-point settings that set voltages with 1 decimal point accuracy
@param new_value The new value the user has selected
@param old_value The previous value
@param config_point The ConfigPoint instance the user is editing
@param arg A user-defined argument, in this case cvN that we're setting the voltage for
"""
arg.voltage(new_value)
def set_digital_cv(self, new_value, old_value, config_point, arg=None):
"""
Callback function for the CV4-6 menu items
These are boolean settings that turn gate signals on/off
@param new_value The new value the user has selected
@param old_value The previous value
@param config_point The ConfigPoint instance the user is editing
@param arg A user-defined argument, in this case cvN that we're setting the voltage for
"""
if new_value:
arg.on()
else:
arg.off()
def main(self):
while True:
# We can check if the menu's GUI has changed and needs to be re-drawn
# This saves us the CPU cycles that would be used by contantly re-drawing
# the menu. Continually re-drawing the menu CAN be done in applications
# where preserving CPU isn't a priority
if self.menu.ui_dirty:
# We must clear the screen before drawing the menu and
# call .show() afterwards
# You may draw additional graphics/text on top of the menu
# before calling.draw() if desired
oled.fill(0)
self.menu.draw()
oled.show()
# If any of the ConfigPoints have been changed, we can save these so they're
# loaded automatically next time
if self.menu.settings_dirty:
self.menu.save(self._state_filename)
if __name__ == "__main__":
SettingsMenuExample().main()