diff --git a/python_payload/apps/appearance/__init__.py b/python_payload/apps/appearance/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..fd7b0a53186249cb5409f7cb3f63956605460074 --- /dev/null +++ b/python_payload/apps/appearance/__init__.py @@ -0,0 +1,258 @@ +from st3m.application import Application +import math, random, sys_display +from st3m import settings +import leds +import sys_display + + +class App(Application): + def __init__(self, app_ctx): + super().__init__(app_ctx) + + self.x = 23 + self.x_vel = 40 / 1000.0 + + self.y = 0 + self.font_size = 20 + self.delta_ms = 0 + self.right_pressed = False + self.left_pressed = False + self.select_pressed = False + self.angle = 0 + self.focused_widget = 1 + self.active = False + self.num_widgets = 4 + self.overhang = -20 + self.line_height = 24 + self.input.buttons.app.left.repeat_enable(800, 300) + self.input.buttons.app.right.repeat_enable(800, 300) + self.mid_x = 50 + self.led_accumulator_ms = 0 + self.blueish = False + + def draw_widget(self, label): + ctx = self.ctx + self.widget_no += 1 + if not self.active: + if self.select_pressed and self.focused_widget > 0: + self.active = True + self.select_pressed = False + elif self.left_pressed: + self.focused_widget -= 1 + if self.focused_widget < 1: + self.focused_widget = 1 + self.left_pressed = False + elif self.right_pressed: + self.focused_widget += 1 + if self.focused_widget > self.num_widgets - 1: + self.focused_widget = self.num_widgets - 1 + self.right_pressed = False + if self.widget_no == self.focused_widget and not self.active: + ctx.rectangle(-130, int(self.y - self.font_size * 0.8), 260, self.font_size) + ctx.line_width = 2.0 + ctx.rgba(0.8, 0.6, 0.1, 1.0) + ctx.stroke() + ctx.gray(1) + ctx.move_to(self.mid_x, self.y) + ctx.save() + ctx.rgb(0.8, 0.8, 0.8) + ctx.text_align = ctx.RIGHT + ctx.text(label + ": ") + ctx.restore() + self.y += self.line_height + + def draw_choice(self, label, choices, no): + ctx = self.ctx + self.draw_widget(label) + if self.widget_no == self.focused_widget and self.active: + if self.left_pressed: + no -= 1 + if no < 0: + no = 0 + elif self.right_pressed: + no += 1 + if no >= len(choices): + no = len(choices) - 1 + elif self.select_pressed: + self.active = False + self.select_pressed = False + + for a in range(len(choices)): + if a == no and self.active and self.widget_no == self.focused_widget: + ctx.save() + ctx.rgba(0.8, 0.6, 0.1, 1.0) + ctx.rectangle( + ctx.x - 1, + ctx.y - self.font_size * 0.8, + ctx.text_width(choices[a]) + 2, + self.font_size, + ).stroke() + ctx.restore() + ctx.text(choices[a] + " ") + elif a == no: + ctx.save() + ctx.gray(1) + ctx.rectangle( + ctx.x - 1, + ctx.y - self.font_size * 0.8, + ctx.text_width(choices[a]) + 2, + self.font_size, + ).fill() + ctx.gray(0) + ctx.text(choices[a] + " ") + ctx.restore() + else: + ctx.text(choices[a] + " ") + return no + + def draw_number(self, label, step_size, no, unit=""): + ctx = self.ctx + self.draw_widget(label) + ret = no + if self.widget_no == self.focused_widget and self.active: + if self.left_pressed: + ret -= step_size + elif self.right_pressed: + ret += step_size + elif self.select_pressed: + self.active = False + self.select_pressed = False + + if self.active and self.widget_no == self.focused_widget: + ctx.save() + ctx.rgba(0.8, 0.6, 0.1, 1.0) + ctx.rectangle( + ctx.x - 1, + ctx.y - self.font_size * 0.8, + ctx.text_width(str(no)[:4]) + 2, + self.font_size, + ).stroke() + ctx.restore() + ctx.text(str(no)[:4] + unit) + else: + ctx.text(str(no)[:4] + unit) + return ret + + def draw_bg(self): + ctx = self.ctx + ctx.gray(1.0) + ctx.move_to(-100, -80) + wig = self.focused_widget - 1 + if wig < 2: + wig = 2 + if wig > self.num_widgets - 3: + wig = self.num_widgets - 3 + focus_pos = self.overhang + (wig - 0.5) * self.line_height + if focus_pos > 40: + self.overhang -= 7 + if focus_pos < -40: + self.overhang += 7 + self.y = self.overhang + self.widget_no = 0 + ctx.rectangle(-120, -120, 240, 240) + ctx.gray(0) + ctx.fill() + ctx.save() + ctx.translate(self.x, -100) + ctx.font_size = 20 + ctx.gray(0.8) + ctx.text("audio settings") + ctx.restore() + ctx.font_size = self.font_size + self.x += self.delta_ms * self.x_vel + if self.x < -50 or self.x > 50: + self.x_vel *= -1 + self.x += self.delta_ms * self.x_vel + + def draw(self, ctx: Context): + self.ctx = ctx + self.draw_bg() + + tmp = self.draw_number( + "led brightness", 8, int(settings.num_leds_brightness.value) + ) + if tmp < 7: + tmp = 7 + elif tmp > 255: + tmp = 255 + if tmp != settings.num_leds_brightness.value: + settings.num_leds_brightness.set_value(tmp) + leds.set_brightness(settings.num_leds_brightness.value) + + tmp = self.draw_number("led speed", 7, int(settings.num_leds_speed.value)) + if tmp > settings.num_leds_speed.value: + tmp = settings.num_leds_speed.value * 2 + elif tmp < settings.num_leds_speed.value: + tmp = (settings.num_leds_speed.value + 1) // 2 + if tmp < 1: + tmp = 1 + elif tmp > 255: + tmp = 255 + if tmp != settings.num_leds_speed.value: + settings.num_leds_speed.set_value(tmp) + leds.set_slew_rate(settings.num_leds_speed.value) + if 255 == settings.num_leds_speed.value: + leds.set_auto_update(0) + else: + leds.set_auto_update(1) + + tmp = self.draw_number( + "display brightness", + 10, + int(settings.num_display_brightness.value), + unit="%", + ) + if tmp < 5: + tmp = 5 + if tmp > 100: + tmp = 100 + if tmp != settings.num_display_brightness.value: + settings.num_display_brightness.set_value(tmp) + sys_display.set_backlight(settings.num_display_brightness.value) + + self.delta_ms = 0 + self.select_pressed = False + self.left_pressed = False + self.right_pressed = False + + def think(self, ins, delta_ms): + super().think(ins, delta_ms) + self.delta_ms += delta_ms + if self.focused_widget == 2: + self.led_accumulator_ms += delta_ms + if ( + self.input.buttons.app.right.pressed + or self.input.buttons.app.right.repeated + ): + self.right_pressed = True + if self.input.buttons.app.left.pressed or self.input.buttons.app.left.repeated: + self.left_pressed = True + if self.input.buttons.app.middle.pressed: + self.select_pressed = True + + while self.led_accumulator_ms > 500: + self.led_accumulator_ms = self.led_accumulator_ms % 500 + self.leds_toggle() + + def leds_toggle(self): + self.blueish = not self.blueish + if self.blueish: + leds.set_all_rgb(0, 127, 255) + else: + leds.set_all_rgb(127, 0, 255) + leds.update() + + def on_enter(self, vm): + super().on_enter(vm) + settings.load_all() + self.leds_toggle() + + def on_exit(self): + settings.save_all() + super().on_exit() + + +if __name__ == "__main__": + from st3m.run import run_app + + run_app(App) diff --git a/python_payload/apps/appearance/audio_config/__init__.py b/python_payload/apps/appearance/audio_config/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..3df2bed300b26b9028b605db21b372c537fbdafa --- /dev/null +++ b/python_payload/apps/appearance/audio_config/__init__.py @@ -0,0 +1,296 @@ +from st3m.application import Application +import math, random, sys_display +from st3m import settings +import audio + + +class App(Application): + def __init__(self, app_ctx): + super().__init__(app_ctx) + + self.x = 23 + self.x_vel = 40 / 1000.0 + + self.y = 0 + self.font_size = 20 + self.delta_ms = 0 + self.right_pressed = False + self.left_pressed = False + self.select_pressed = False + self.angle = 0 + self.focused_widget = 1 + self.active = False + self.num_widgets = 11 + self.overhang = -70 + self.line_height = 24 + self.input.buttons.app.left.repeat_enable(800, 300) + self.input.buttons.app.right.repeat_enable(800, 300) + self.mid_x = 30 + + def draw_widget(self, label): + ctx = self.ctx + self.widget_no += 1 + if not self.active: + if self.select_pressed and self.focused_widget > 0: + self.active = True + self.select_pressed = False + elif self.left_pressed: + self.focused_widget -= 1 + if self.focused_widget < 1: + self.focused_widget = 1 + self.left_pressed = False + elif self.right_pressed: + self.focused_widget += 1 + if self.focused_widget > self.num_widgets - 1: + self.focused_widget = self.num_widgets - 1 + self.right_pressed = False + if self.widget_no == self.focused_widget and not self.active: + ctx.rectangle(-130, int(self.y - self.font_size * 0.8), 260, self.font_size) + ctx.line_width = 2.0 + ctx.rgba(0.8, 0.6, 0.1, 1.0) + ctx.stroke() + ctx.gray(1) + ctx.move_to(self.mid_x, self.y) + ctx.save() + ctx.rgb(0.8, 0.8, 0.8) + ctx.text_align = ctx.RIGHT + ctx.text(label + ": ") + ctx.restore() + self.y += self.line_height + + def draw_choice(self, label, choices, no): + ctx = self.ctx + self.draw_widget(label) + if self.widget_no == self.focused_widget and self.active: + if self.left_pressed: + no -= 1 + if no < 0: + no = 0 + elif self.right_pressed: + no += 1 + if no >= len(choices): + no = len(choices) - 1 + elif self.select_pressed: + self.active = False + self.select_pressed = False + + for a in range(len(choices)): + if a == no and self.active and self.widget_no == self.focused_widget: + ctx.save() + ctx.rgba(0.8, 0.6, 0.1, 1.0) + ctx.rectangle( + ctx.x - 1, + ctx.y - self.font_size * 0.8, + ctx.text_width(choices[a]) + 2, + self.font_size, + ).stroke() + ctx.restore() + ctx.text(choices[a] + " ") + elif a == no: + ctx.save() + ctx.gray(1) + ctx.rectangle( + ctx.x - 1, + ctx.y - self.font_size * 0.8, + ctx.text_width(choices[a]) + 2, + self.font_size, + ).fill() + ctx.gray(0) + ctx.text(choices[a] + " ") + ctx.restore() + else: + ctx.text(choices[a] + " ") + return no + + def draw_number(self, label, step_size, no, unit=""): + ctx = self.ctx + self.draw_widget(label) + ret = no + if self.widget_no == self.focused_widget and self.active: + if self.left_pressed: + ret -= step_size + elif self.right_pressed: + ret += step_size + elif self.select_pressed: + self.active = False + self.select_pressed = False + + if self.active and self.widget_no == self.focused_widget: + ctx.save() + ctx.rgba(0.8, 0.6, 0.1, 1.0) + ctx.rectangle( + ctx.x - 1, + ctx.y - self.font_size * 0.8, + ctx.text_width(str(no)[:4]) + 2, + self.font_size, + ).stroke() + ctx.restore() + ctx.text(str(no)[:4] + unit) + else: + ctx.text(str(no)[:4] + unit) + return ret + + def draw_bg(self): + ctx = self.ctx + ctx.gray(1.0) + ctx.move_to(-100, -80) + wig = self.focused_widget - 1 + if wig < 2: + wig = 2 + if wig > self.num_widgets - 3: + wig = self.num_widgets - 3 + focus_pos = self.overhang + (wig - 0.5) * self.line_height + if focus_pos > 40: + self.overhang -= 7 + if focus_pos < -40: + self.overhang += 7 + self.y = self.overhang + self.widget_no = 0 + ctx.rectangle(-120, -120, 240, 240) + ctx.gray(0) + ctx.fill() + ctx.save() + ctx.translate(self.x, -100) + ctx.font_size = 20 + ctx.gray(0.8) + ctx.text("audio settings") + ctx.restore() + ctx.font_size = self.font_size + self.x += self.delta_ms * self.x_vel + if self.x < -50 or self.x > 50: + self.x_vel *= -1 + self.x += self.delta_ms * self.x_vel + + def draw(self, ctx: Context): + self.ctx = ctx + self.draw_bg() + + tmp = self.draw_number( + "vol step", 0.5, float(settings.num_volume_step_db.value), unit="dB" + ) + if tmp < 0.5: + tmp = 0.5 + if tmp > 5: + tmp = 5 + settings.num_volume_step_db.set_value(tmp) + + tmp = self.draw_number( + "vol repeat step", + 0.5, + float(settings.num_volume_repeat_step_db.value), + unit="dB", + ) + if tmp < 0: + tmp = 0 + if tmp > 5: + tmp = 5 + settings.num_volume_repeat_step_db.set_value(tmp) + + tmp = self.draw_number( + "vol repeat wait", + 50, + int(settings.num_volume_repeat_wait_ms.value), + unit="ms", + ) + if tmp < 100: + tmp = 100 + if tmp > 1000: + tmp = 1000 + settings.num_volume_repeat_wait_ms.set_value(tmp) + + tmp = self.draw_number( + "vol repeat", 50, int(settings.num_volume_repeat_ms.value), unit="ms" + ) + if tmp < 100: + tmp = 100 + if tmp > 1000: + tmp = 1000 + settings.num_volume_repeat_ms.set_value(tmp) + + tmp = self.draw_number( + "phones startup", + 1, + int(settings.num_headphones_startup_volume_db.value), + unit="dB", + ) + if tmp < -70: + tmp = -70 + if tmp > 3: + tmp = 3 + settings.num_headphones_startup_volume_db.set_value(tmp) + + tmp = self.draw_number( + "phones min", 1, int(settings.num_headphones_min_db.value), unit="dB" + ) + if settings.num_headphones_min_db.value != tmp: + audio.headphones_set_minimum_volume_dB(tmp) + settings.num_headphones_min_db.set_value( + audio.headphones_get_minimum_volume_dB() + ) + + tmp = self.draw_number( + "phones max", 1, int(settings.num_headphones_max_db.value), unit="dB" + ) + if settings.num_headphones_max_db.value != tmp: + audio.headphones_set_maximum_volume_dB(tmp) + settings.num_headphones_max_db.set_value( + audio.headphones_get_maximum_volume_dB() + ) + + tmp = self.draw_number( + "speaker startup", + 1, + int(settings.num_speaker_startup_volume_db.value), + unit="dB", + ) + if tmp < -60: + tmp = -60 + if tmp > 14: + tmp = 14 + settings.num_speaker_startup_volume_db.set_value(tmp) + + tmp = self.draw_number( + "speaker min", 1, int(settings.num_speaker_min_db.value), unit="dB" + ) + if settings.num_speaker_min_db.value != tmp: + audio.speaker_set_minimum_volume_dB(tmp) + settings.num_speaker_min_db.set_value(audio.speaker_get_minimum_volume_dB()) + + tmp = self.draw_number( + "speaker max", 1, int(settings.num_speaker_max_db.value), unit="dB" + ) + if settings.num_speaker_max_db.value != tmp: + audio.speaker_set_maximum_volume_dB(tmp) + settings.num_speaker_max_db.set_value(audio.speaker_get_maximum_volume_dB()) + + self.delta_ms = 0 + self.select_pressed = False + self.left_pressed = False + self.right_pressed = False + + def think(self, ins, delta_ms): + super().think(ins, delta_ms) + self.delta_ms += delta_ms + if ( + self.input.buttons.app.right.pressed + or self.input.buttons.app.right.repeated + ): + self.right_pressed = True + if self.input.buttons.app.left.pressed or self.input.buttons.app.left.repeated: + self.left_pressed = True + if self.input.buttons.app.middle.pressed: + self.select_pressed = True + + def on_enter(self, vm): + super().on_enter(vm) + settings.load_all() + + def on_exit(self): + settings.save_all() + super().on_exit() + + +if __name__ == "__main__": + from st3m.run import run_app + + run_app(App) diff --git a/python_payload/apps/appearance/audio_config/flow3r.toml b/python_payload/apps/appearance/audio_config/flow3r.toml new file mode 100644 index 0000000000000000000000000000000000000000..31ab43fbd9fed65189ac75ab20ecaaae8b3a81f2 --- /dev/null +++ b/python_payload/apps/appearance/audio_config/flow3r.toml @@ -0,0 +1,8 @@ +[app] +name = "Audio Config" +menu = "Hidden" + +[metadata] +author = "Flow3r Badge Authors" +license = "LGPL-3.0-only" +url = "https://git.flow3r.garden/flow3r/flow3r-firmware" diff --git a/python_payload/apps/appearance/flow3r.toml b/python_payload/apps/appearance/flow3r.toml new file mode 100644 index 0000000000000000000000000000000000000000..fe2957f7256d9fa025b61e8c13952dd98858594f --- /dev/null +++ b/python_payload/apps/appearance/flow3r.toml @@ -0,0 +1,8 @@ +[app] +name = "Appearance" +menu = "Hidden" + +[metadata] +author = "Flow3r Badge Authors" +license = "LGPL-3.0-only" +url = "https://git.flow3r.garden/flow3r/flow3r-firmware" diff --git a/python_payload/apps/audio_config/__init__.py b/python_payload/apps/audio_config/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..3df2bed300b26b9028b605db21b372c537fbdafa --- /dev/null +++ b/python_payload/apps/audio_config/__init__.py @@ -0,0 +1,296 @@ +from st3m.application import Application +import math, random, sys_display +from st3m import settings +import audio + + +class App(Application): + def __init__(self, app_ctx): + super().__init__(app_ctx) + + self.x = 23 + self.x_vel = 40 / 1000.0 + + self.y = 0 + self.font_size = 20 + self.delta_ms = 0 + self.right_pressed = False + self.left_pressed = False + self.select_pressed = False + self.angle = 0 + self.focused_widget = 1 + self.active = False + self.num_widgets = 11 + self.overhang = -70 + self.line_height = 24 + self.input.buttons.app.left.repeat_enable(800, 300) + self.input.buttons.app.right.repeat_enable(800, 300) + self.mid_x = 30 + + def draw_widget(self, label): + ctx = self.ctx + self.widget_no += 1 + if not self.active: + if self.select_pressed and self.focused_widget > 0: + self.active = True + self.select_pressed = False + elif self.left_pressed: + self.focused_widget -= 1 + if self.focused_widget < 1: + self.focused_widget = 1 + self.left_pressed = False + elif self.right_pressed: + self.focused_widget += 1 + if self.focused_widget > self.num_widgets - 1: + self.focused_widget = self.num_widgets - 1 + self.right_pressed = False + if self.widget_no == self.focused_widget and not self.active: + ctx.rectangle(-130, int(self.y - self.font_size * 0.8), 260, self.font_size) + ctx.line_width = 2.0 + ctx.rgba(0.8, 0.6, 0.1, 1.0) + ctx.stroke() + ctx.gray(1) + ctx.move_to(self.mid_x, self.y) + ctx.save() + ctx.rgb(0.8, 0.8, 0.8) + ctx.text_align = ctx.RIGHT + ctx.text(label + ": ") + ctx.restore() + self.y += self.line_height + + def draw_choice(self, label, choices, no): + ctx = self.ctx + self.draw_widget(label) + if self.widget_no == self.focused_widget and self.active: + if self.left_pressed: + no -= 1 + if no < 0: + no = 0 + elif self.right_pressed: + no += 1 + if no >= len(choices): + no = len(choices) - 1 + elif self.select_pressed: + self.active = False + self.select_pressed = False + + for a in range(len(choices)): + if a == no and self.active and self.widget_no == self.focused_widget: + ctx.save() + ctx.rgba(0.8, 0.6, 0.1, 1.0) + ctx.rectangle( + ctx.x - 1, + ctx.y - self.font_size * 0.8, + ctx.text_width(choices[a]) + 2, + self.font_size, + ).stroke() + ctx.restore() + ctx.text(choices[a] + " ") + elif a == no: + ctx.save() + ctx.gray(1) + ctx.rectangle( + ctx.x - 1, + ctx.y - self.font_size * 0.8, + ctx.text_width(choices[a]) + 2, + self.font_size, + ).fill() + ctx.gray(0) + ctx.text(choices[a] + " ") + ctx.restore() + else: + ctx.text(choices[a] + " ") + return no + + def draw_number(self, label, step_size, no, unit=""): + ctx = self.ctx + self.draw_widget(label) + ret = no + if self.widget_no == self.focused_widget and self.active: + if self.left_pressed: + ret -= step_size + elif self.right_pressed: + ret += step_size + elif self.select_pressed: + self.active = False + self.select_pressed = False + + if self.active and self.widget_no == self.focused_widget: + ctx.save() + ctx.rgba(0.8, 0.6, 0.1, 1.0) + ctx.rectangle( + ctx.x - 1, + ctx.y - self.font_size * 0.8, + ctx.text_width(str(no)[:4]) + 2, + self.font_size, + ).stroke() + ctx.restore() + ctx.text(str(no)[:4] + unit) + else: + ctx.text(str(no)[:4] + unit) + return ret + + def draw_bg(self): + ctx = self.ctx + ctx.gray(1.0) + ctx.move_to(-100, -80) + wig = self.focused_widget - 1 + if wig < 2: + wig = 2 + if wig > self.num_widgets - 3: + wig = self.num_widgets - 3 + focus_pos = self.overhang + (wig - 0.5) * self.line_height + if focus_pos > 40: + self.overhang -= 7 + if focus_pos < -40: + self.overhang += 7 + self.y = self.overhang + self.widget_no = 0 + ctx.rectangle(-120, -120, 240, 240) + ctx.gray(0) + ctx.fill() + ctx.save() + ctx.translate(self.x, -100) + ctx.font_size = 20 + ctx.gray(0.8) + ctx.text("audio settings") + ctx.restore() + ctx.font_size = self.font_size + self.x += self.delta_ms * self.x_vel + if self.x < -50 or self.x > 50: + self.x_vel *= -1 + self.x += self.delta_ms * self.x_vel + + def draw(self, ctx: Context): + self.ctx = ctx + self.draw_bg() + + tmp = self.draw_number( + "vol step", 0.5, float(settings.num_volume_step_db.value), unit="dB" + ) + if tmp < 0.5: + tmp = 0.5 + if tmp > 5: + tmp = 5 + settings.num_volume_step_db.set_value(tmp) + + tmp = self.draw_number( + "vol repeat step", + 0.5, + float(settings.num_volume_repeat_step_db.value), + unit="dB", + ) + if tmp < 0: + tmp = 0 + if tmp > 5: + tmp = 5 + settings.num_volume_repeat_step_db.set_value(tmp) + + tmp = self.draw_number( + "vol repeat wait", + 50, + int(settings.num_volume_repeat_wait_ms.value), + unit="ms", + ) + if tmp < 100: + tmp = 100 + if tmp > 1000: + tmp = 1000 + settings.num_volume_repeat_wait_ms.set_value(tmp) + + tmp = self.draw_number( + "vol repeat", 50, int(settings.num_volume_repeat_ms.value), unit="ms" + ) + if tmp < 100: + tmp = 100 + if tmp > 1000: + tmp = 1000 + settings.num_volume_repeat_ms.set_value(tmp) + + tmp = self.draw_number( + "phones startup", + 1, + int(settings.num_headphones_startup_volume_db.value), + unit="dB", + ) + if tmp < -70: + tmp = -70 + if tmp > 3: + tmp = 3 + settings.num_headphones_startup_volume_db.set_value(tmp) + + tmp = self.draw_number( + "phones min", 1, int(settings.num_headphones_min_db.value), unit="dB" + ) + if settings.num_headphones_min_db.value != tmp: + audio.headphones_set_minimum_volume_dB(tmp) + settings.num_headphones_min_db.set_value( + audio.headphones_get_minimum_volume_dB() + ) + + tmp = self.draw_number( + "phones max", 1, int(settings.num_headphones_max_db.value), unit="dB" + ) + if settings.num_headphones_max_db.value != tmp: + audio.headphones_set_maximum_volume_dB(tmp) + settings.num_headphones_max_db.set_value( + audio.headphones_get_maximum_volume_dB() + ) + + tmp = self.draw_number( + "speaker startup", + 1, + int(settings.num_speaker_startup_volume_db.value), + unit="dB", + ) + if tmp < -60: + tmp = -60 + if tmp > 14: + tmp = 14 + settings.num_speaker_startup_volume_db.set_value(tmp) + + tmp = self.draw_number( + "speaker min", 1, int(settings.num_speaker_min_db.value), unit="dB" + ) + if settings.num_speaker_min_db.value != tmp: + audio.speaker_set_minimum_volume_dB(tmp) + settings.num_speaker_min_db.set_value(audio.speaker_get_minimum_volume_dB()) + + tmp = self.draw_number( + "speaker max", 1, int(settings.num_speaker_max_db.value), unit="dB" + ) + if settings.num_speaker_max_db.value != tmp: + audio.speaker_set_maximum_volume_dB(tmp) + settings.num_speaker_max_db.set_value(audio.speaker_get_maximum_volume_dB()) + + self.delta_ms = 0 + self.select_pressed = False + self.left_pressed = False + self.right_pressed = False + + def think(self, ins, delta_ms): + super().think(ins, delta_ms) + self.delta_ms += delta_ms + if ( + self.input.buttons.app.right.pressed + or self.input.buttons.app.right.repeated + ): + self.right_pressed = True + if self.input.buttons.app.left.pressed or self.input.buttons.app.left.repeated: + self.left_pressed = True + if self.input.buttons.app.middle.pressed: + self.select_pressed = True + + def on_enter(self, vm): + super().on_enter(vm) + settings.load_all() + + def on_exit(self): + settings.save_all() + super().on_exit() + + +if __name__ == "__main__": + from st3m.run import run_app + + run_app(App) diff --git a/python_payload/apps/audio_config/flow3r.toml b/python_payload/apps/audio_config/flow3r.toml new file mode 100644 index 0000000000000000000000000000000000000000..31ab43fbd9fed65189ac75ab20ecaaae8b3a81f2 --- /dev/null +++ b/python_payload/apps/audio_config/flow3r.toml @@ -0,0 +1,8 @@ +[app] +name = "Audio Config" +menu = "Hidden" + +[metadata] +author = "Flow3r Badge Authors" +license = "LGPL-3.0-only" +url = "https://git.flow3r.garden/flow3r/flow3r-firmware" diff --git a/python_payload/apps/graphics_mode/__init__.py b/python_payload/apps/graphics_mode/__init__.py index 5a4bd83b203bd5e2b33a9c81f2304cb7b41680af..40296bcc134d94730177a2b02a8f7325e81da0ce 100644 --- a/python_payload/apps/graphics_mode/__init__.py +++ b/python_payload/apps/graphics_mode/__init__.py @@ -18,6 +18,8 @@ class App(Application): self.angle = 0 self.focused_widget = 2 self.active = False + self.min_focus = 0 + self.min_focus = 3 def draw_widget(self, label): ctx = self.ctx diff --git a/python_payload/st3m/application.py b/python_payload/st3m/application.py index 4d1dc47431b35017727a4c05cc256c59f6dae48a..b49557aad204da586169adecc65d1af8f5b91c79 100644 --- a/python_payload/st3m/application.py +++ b/python_payload/st3m/application.py @@ -67,8 +67,11 @@ class Application(BaseView): st3m.wifi.setup_wifi() elif self._wifi_preference is False: st3m.wifi.disable() - leds.set_auto_update(0) - leds.set_slew_rate(255) + leds.set_slew_rate(settings.num_leds_speed.value) + if 255 == settings.num_leds_speed.value: + leds.set_auto_update(0) + else: + leds.set_auto_update(1) super().on_enter(vm) def on_exit(self) -> None: diff --git a/python_payload/st3m/processors.py b/python_payload/st3m/processors.py index be45fd771ec5022dad715d3b97794e60d06b21a0..033545d9d08cf4053b6d7bb18669736241eba537 100644 --- a/python_payload/st3m/processors.py +++ b/python_payload/st3m/processors.py @@ -30,13 +30,42 @@ class AudioProcessor(Processor): def __init__(self) -> None: super().__init__() self.input = InputController() + self.repeat_wait_ms = 800 + self.repeat_ms = 300 + self._update_repeat() + + def _update_repeat(self): + changed = False + if self.repeat_wait_ms != settings.num_volume_repeat_wait_ms.value: + changed = True + if self.repeat_ms != settings.num_volume_repeat_ms.value: + changed = True + if changed: + self.repeat_wait_ms = settings.num_volume_repeat_wait_ms.value + self.repeat_ms = settings.num_volume_repeat_ms.value + self.input.buttons.os.left.repeat_enable( + self.repeat_wait_ms, self.repeat_ms + ) + self.input.buttons.os.right.repeat_enable( + self.repeat_wait_ms, self.repeat_ms + ) def think(self, ins: InputState, delta_ms: int) -> None: self.input.think(ins, delta_ms) - if self.input.buttons.os.left.pressed: + os_button = self.input.buttons.os + event = True + if os_button.left.pressed: audio.adjust_volume_dB(-settings.num_volume_step_db.value) - if self.input.buttons.os.right.pressed: + elif os_button.right.pressed: audio.adjust_volume_dB(settings.num_volume_step_db.value) + elif os_button.left.repeated: + audio.adjust_volume_dB(-settings.num_volume_repeat_step_db.value) + elif os_button.right.repeated: + audio.adjust_volume_dB(settings.num_volume_repeat_step_db.value) + else: + event = False + if event: + self._update_repeat() class ProcessorMidldeware(Responder): diff --git a/python_payload/st3m/run.py b/python_payload/st3m/run.py index 0b7761dcc75bf48bd800080308b65f8d6d610ea6..f609dead4f0f2c241ddb2708b97b474a05ff073a 100644 --- a/python_payload/st3m/run.py +++ b/python_payload/st3m/run.py @@ -151,9 +151,16 @@ def run_main() -> None: audio.headphones_set_volume_dB(settings.num_headphones_startup_volume_db.value) audio.speaker_set_volume_dB(settings.num_speaker_startup_volume_db.value) audio.headphones_set_minimum_volume_dB(settings.num_headphones_min_db.value) - audio.speaker_set_minimum_volume_dB(settings.num_speakers_min_db.value) + audio.speaker_set_minimum_volume_dB(settings.num_speaker_min_db.value) audio.headphones_set_maximum_volume_dB(settings.num_headphones_max_db.value) - audio.speaker_set_maximum_volume_dB(settings.num_speakers_max_db.value) + audio.speaker_set_maximum_volume_dB(settings.num_speaker_max_db.value) + leds.set_brightness(settings.num_leds_brightness.value) + leds.set_slew_rate(settings.num_leds_speed.value) + if 255 == settings.num_leds_speed.value: + leds.set_auto_update(0) + else: + leds.set_auto_update(1) + sys_display.set_backlight(settings.num_display_brightness.value) leds.set_rgb(0, 255, 0, 0) leds.update() diff --git a/python_payload/st3m/settings.py b/python_payload/st3m/settings.py index 6cd7409d65f80518e462e836cf5f5efa62dfdb1c..48f62a22bc0dd0c154e599e83f434999a2e57d63 100644 --- a/python_payload/st3m/settings.py +++ b/python_payload/st3m/settings.py @@ -207,9 +207,20 @@ onoff_wifi_preference = OnOffTunable( str_wifi_ssid = StringTunable("WiFi SSID", "system.wifi.ssid", "Camp2023-open") str_wifi_psk = ObfuscatedStringTunable("WiFi Password", "system.wifi.psk", None) str_hostname = StringTunable("Hostname", "system.hostname", "flow3r") + num_volume_step_db = StringTunable( - "Volume Change dB", "system.audio.volume_step_dB", 2.5 + "Volume Change dB", "system.audio.volume_step_dB", 1.5 +) +num_volume_repeat_step_db = StringTunable( + "Volume Repeat Change dB", "system.audio.volume_repeat_step_dB", 2.5 +) +num_volume_repeat_wait_ms = StringTunable( + "Volume Repeat Wait Time ms", "system.audio.volume_repeat_wait_ms", 800 +) +num_volume_repeat_ms = StringTunable( + "Volume Repeat Time ms", "system.audio.volume_repeat_ms", 300 ) + num_speaker_startup_volume_db = StringTunable( "Speaker Startup Volume dB", "system.audio.speaker_startup_volume_dB", -10 ) @@ -219,15 +230,22 @@ num_headphones_startup_volume_db = StringTunable( num_headphones_min_db = StringTunable( "Min Headphone Volume dB", "system.audio.headphones_min_dB", -45 ) -num_speakers_min_db = StringTunable( - "Min Speakers Volume dB", "system.audio.speakers_min_dB", -40 +num_speaker_min_db = StringTunable( + "Min Speaker Volume dB", "system.audio.speakers_min_dB", -40 ) num_headphones_max_db = StringTunable( "Max Headphone Volume dB", "system.audio.headphones_max_dB", 3 ) -num_speakers_max_db = StringTunable( - "Max Speakers Volume dB", "system.audio.speakers_max_dB", 14 +num_speaker_max_db = StringTunable( + "Max Speaker Volume dB", "system.audio.speakers_max_dB", 14 +) + +num_display_brightness = StringTunable( + "Display Brightness", "system.brightness.display", 100 ) +num_leds_brightness = StringTunable("LED Brightness", "system.brightness.leds", 200) + +num_leds_speed = StringTunable("LED speed", "system.brightness.leds_speed", 255) # List of all settings to be loaded/saved load_save_settings: List[UnaryTunable] = [ @@ -243,12 +261,18 @@ load_save_settings: List[UnaryTunable] = [ str_wifi_psk, str_hostname, num_volume_step_db, + num_volume_repeat_step_db, + num_volume_repeat_wait_ms, + num_volume_repeat_ms, num_speaker_startup_volume_db, num_headphones_startup_volume_db, num_headphones_min_db, - num_speakers_min_db, + num_speaker_min_db, num_headphones_max_db, - num_speakers_max_db, + num_speaker_max_db, + num_display_brightness, + num_leds_brightness, + num_leds_speed, ] diff --git a/python_payload/st3m/settings_menu.py b/python_payload/st3m/settings_menu.py index c775baacf4b16ee2567645a07b05a5f96914c365..6a0eeb432f5f28ca1d58d16bc4e26c8c48242856 100644 --- a/python_payload/st3m/settings_menu.py +++ b/python_payload/st3m/settings_menu.py @@ -214,6 +214,8 @@ if TYPE_CHECKING: # Main settings menu settings_menu_structure: "MenuStructure" = [ MenuItemAppLaunch(BundleMetadata("/flash/sys/apps/w1f1")), + MenuItemAppLaunch(BundleMetadata("/flash/sys/apps/audio_config")), + MenuItemAppLaunch(BundleMetadata("/flash/sys/apps/appearance")), onoff_wifi, onoff_wifi_preference, onoff_show_tray, diff --git a/sim/fakes/leds.py b/sim/fakes/leds.py index 6df4deb57d7c42ccf4769186be3c927a29a55a46..c7144899bcab079f133c49b627ab39d76bf40894 100644 --- a/sim/fakes/leds.py +++ b/sim/fakes/leds.py @@ -47,3 +47,7 @@ def update(): def set_auto_update(b: int): pass + + +def set_brightness(b: float): + pass diff --git a/sim/fakes/sys_display.py b/sim/fakes/sys_display.py index a2f38c76a7eb5868674464ca6ebdeff98c3860aa..f8aff92572d848a13640a699708172c02fa7f33b 100644 --- a/sim/fakes/sys_display.py +++ b/sim/fakes/sys_display.py @@ -25,3 +25,7 @@ osd = 256 def ctx(foo): return _sim.get_ctx() + + +def set_backlight(a): + pass