Added the WelcomeScreen library
This commit is contained in:
parent
bd396913fe
commit
355821a6a9
126
lib/WelcomeScreen.py
Normal file
126
lib/WelcomeScreen.py
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
"""
|
||||||
|
WelcomeScreen: A simple library providing a customizable welcome screen fading over an LCD
|
||||||
|
Copyright (C) 2024 Benjamin Burkhardt
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
|
|
||||||
|
class WelcomeScreen:
|
||||||
|
# __init__() - the constructor
|
||||||
|
# lcd: an object of I2C_LCD (from the PCF8574T library - https://git.privacynerd.de/BlueFox/micropython-libraries/src/branch/main/PCF8574T)
|
||||||
|
# ---
|
||||||
|
# interrupt_pins: a list containing machine.Pin objects exclusively (but if you give these you can still turn interrupting off
|
||||||
|
# via a parameter in the show method (see below!)
|
||||||
|
# ---
|
||||||
|
# subtitle: the text shown below the cycling text (e.g. the device's name, ...) (Lorem ipsum. by default)
|
||||||
|
# ---
|
||||||
|
# starting_msg: the text shown while cycling (default: Starting...)
|
||||||
|
# ---
|
||||||
|
# started_msg: the text shown while cycling (default: Started!)
|
||||||
|
def __init__(self, lcd, interrupt_pins=None, subtitle="Lorem ipsum.", starting_msg="Starting...", started_msg="Started!"):
|
||||||
|
self.lcd = lcd
|
||||||
|
self.columns = self.lcd.num_columns
|
||||||
|
self.lines = self.lcd.num_lines
|
||||||
|
|
||||||
|
self.interrupt_pins = interrupt_pins
|
||||||
|
|
||||||
|
self.subtitle = subtitle
|
||||||
|
self.starting_msg = starting_msg
|
||||||
|
self.started_msg = started_msg
|
||||||
|
|
||||||
|
|
||||||
|
# show() - Display the actual message
|
||||||
|
# ---
|
||||||
|
# cycles says how often the Starting text goes through
|
||||||
|
# ---
|
||||||
|
# wait_after_cycles is a number in seconds (can be float) defining how long to wait before returning OR
|
||||||
|
# if fading out is activated, the time to wait between end of the cycling animation and the fade out animation
|
||||||
|
# ---
|
||||||
|
# fade_down is a dict with following keys:
|
||||||
|
# - "enabled" - REQUIRED - wether fading is enabled (default: true)
|
||||||
|
# - "wait_between" - OPTIONAL - the time in seconds to wait between each line fade
|
||||||
|
# - "wait_after" - OPTIONAL - the time in seconds to wait after the fade out
|
||||||
|
# ---
|
||||||
|
# interruptable influences wether the program can be interrupted by pins in the self.interrupt_pins list
|
||||||
|
# if this list is empty, even when interruptable is set to true, nothing will be able to interrupt!
|
||||||
|
def show(self, cycles=1, wait_after_cycles=1, fade_down={"enabled": True}, interruptable=True):
|
||||||
|
if cycles < 1: cycles = 1
|
||||||
|
padding = " " * self.columns # as much spaces as padding as one display line is long
|
||||||
|
padding_hyphen = "-" * self.columns # as much hyphens as padding as one display line is long
|
||||||
|
|
||||||
|
# mechanism for centering on a 4*20 display
|
||||||
|
y_offset = 0
|
||||||
|
if self.lines == 4:
|
||||||
|
y_offset = 1
|
||||||
|
# also clear the top and bottom with ----
|
||||||
|
self.lcd.move_to(0,0)
|
||||||
|
self.lcd.putstr(padding_hyphen)
|
||||||
|
self.lcd.move_to(0,4)
|
||||||
|
self.lcd.putstr(padding_hyphen)
|
||||||
|
|
||||||
|
# get the current pin values (only if there are pins specified) (when something changes, the interrupt happens and the cycle stops)
|
||||||
|
break_flag = False
|
||||||
|
if self.interrupt_pins:
|
||||||
|
pin_values = []
|
||||||
|
for p in self.interrupt_pins:
|
||||||
|
pin_values.append(p.value())
|
||||||
|
# cycle the text 'cycles' times and listen for changes on interrupt pins (if any given)
|
||||||
|
for i in range(cycles):
|
||||||
|
line1 = padding + self.starting_msg + padding
|
||||||
|
line2 = self.subtitle.center(self.columns)
|
||||||
|
for i in range(self.columns + len(self.starting_msg)):
|
||||||
|
self.lcd.move_to(0,y_offset)
|
||||||
|
self.lcd.putstr(line1[0:self.columns])
|
||||||
|
self.lcd.move_to(0,y_offset+1)
|
||||||
|
self.lcd.putstr(line2[0:self.columns])
|
||||||
|
line1 = line1[1:]
|
||||||
|
if self.interrupt_pins:
|
||||||
|
for i, p in enumerate(self.interrupt_pins):
|
||||||
|
if pin_values[i] != p.value():
|
||||||
|
break_flag = True
|
||||||
|
if break_flag:
|
||||||
|
break
|
||||||
|
if break_flag:
|
||||||
|
break
|
||||||
|
|
||||||
|
self.lcd.move_to(0,y_offset)
|
||||||
|
self.lcd.putstr(self.started_msg.center(16))
|
||||||
|
|
||||||
|
sleep(wait_after_cycles)
|
||||||
|
|
||||||
|
# now fade down if enabled via the params
|
||||||
|
if fade_down["enabled"]:
|
||||||
|
# get all the waiting times
|
||||||
|
if "wait_between" in fade_down.keys():
|
||||||
|
wait_between = fade_down["wait_between"]
|
||||||
|
else:
|
||||||
|
wait_between = 0.1
|
||||||
|
if "wait_after" in fade_down.keys():
|
||||||
|
wait_after = fade_down["wait_after"]
|
||||||
|
else:
|
||||||
|
wait_after = 0.3
|
||||||
|
if self.lines == 4:
|
||||||
|
old_display = padding_hyphen + self.started_msg.center(16) + self.subtitle.center(self.columns) + padding_hyphen
|
||||||
|
else:
|
||||||
|
old_display = self.started_msg.center(16) + self.subtitle.center(self.columns)
|
||||||
|
self.lcd.move_to(0,0) # move to the start of the lcd
|
||||||
|
while old_display != "":
|
||||||
|
old_display = old_display[:-self.columns]
|
||||||
|
lines_before = " " * (self.columns*self.lines-len(old_display))
|
||||||
|
self.lcd.putstr(lines_before + old_display)
|
||||||
|
sleep(wait_between)
|
||||||
|
sleep(wait_after)
|
14
main.py
14
main.py
@ -12,6 +12,7 @@ You should have received a copy of the GNU General Public License along with thi
|
|||||||
|
|
||||||
import config, utils
|
import config, utils
|
||||||
from lib.ProgramChooserAdapted import ProgramChooser
|
from lib.ProgramChooserAdapted import ProgramChooser
|
||||||
|
from lib.WelcomeScreen import WelcomeScreen
|
||||||
from time import sleep
|
from time import sleep
|
||||||
import gc # garbage collector for better memory performance
|
import gc # garbage collector for better memory performance
|
||||||
|
|
||||||
@ -61,10 +62,17 @@ programs = {
|
|||||||
"UV on": uv_on,
|
"UV on": uv_on,
|
||||||
"Timer": timer,
|
"Timer": timer,
|
||||||
"Manual": manual,
|
"Manual": manual,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.STARTUP_WELCOME_SHOW:
|
||||||
if config.STARTUP_WELCOME_SHOW: utils.show_welcome()
|
ws = WelcomeScreen(config.LCD,
|
||||||
|
interrupt_pins=[config.BTN_1, config.BTN_2, config.SWITCH],
|
||||||
|
subtitle=config.STARTUP_PROJECT_NAME,
|
||||||
|
starting_msg=config.STARTUP_MESSAGE_STARTING,
|
||||||
|
started_msg=config.STARTUP_MESSAGE_FINISHED)
|
||||||
|
ws.show(cycles=config.STARTUP_WELCOME_CYCLES)
|
||||||
|
del ws
|
||||||
|
gc.collect()
|
||||||
|
|
||||||
pc = ProgramChooser(programs) # initialize the ProgramChooser
|
pc = ProgramChooser(programs) # initialize the ProgramChooser
|
||||||
pc.run() # and run it (will be an endless loop)
|
pc.run() # and run it (will be an endless loop)
|
||||||
|
34
utils.py
34
utils.py
@ -27,37 +27,3 @@ def log(log_level: int, message: str):
|
|||||||
elif cfg.LOG_LEVEL >= log_level: # if log level is valid
|
elif cfg.LOG_LEVEL >= log_level: # if log level is valid
|
||||||
print(f"[{log_mapping[log_level]}] {message}")
|
print(f"[{log_mapping[log_level]}] {message}")
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
Simple function that displays a startup "welcome" screen
|
|
||||||
Configurable in config.py
|
|
||||||
"""
|
|
||||||
def show_welcome(): # cycles says how often the startup text goes through
|
|
||||||
cycles = cfg.STARTUP_WELCOME_CYCLES
|
|
||||||
if cycles < 1:
|
|
||||||
cycles = 1
|
|
||||||
|
|
||||||
padding = " "*cfg.LCD_I2C_NUM_COLS
|
|
||||||
started_str = cfg.STARTUP_MESSAGE_FINISHED
|
|
||||||
starting_str = cfg.STARTUP_MESSAGE_STARTING
|
|
||||||
|
|
||||||
|
|
||||||
# slide the first line over the display (animated from right to left)
|
|
||||||
for i in range(cycles):
|
|
||||||
line1 = padding + starting_str + padding
|
|
||||||
line2 = cfg.STARTUP_PROJECT_NAME
|
|
||||||
for i in range(cfg.LCD_I2C_NUM_COLS + len(starting_str)):
|
|
||||||
cfg.LCD.putstr(line1[0:16])
|
|
||||||
cfg.LCD.move_to(0,1)
|
|
||||||
cfg.LCD.putstr(line2[0:16])
|
|
||||||
line1 = line1[1:]
|
|
||||||
|
|
||||||
cfg.LCD.move_to(0,0)
|
|
||||||
cfg.LCD.putstr(started_str)
|
|
||||||
|
|
||||||
# now fade down
|
|
||||||
sleep(2)
|
|
||||||
cfg.LCD.move_to(0,0)
|
|
||||||
cfg.LCD.putstr(padding + started_str)
|
|
||||||
sleep(0.1)
|
|
||||||
cfg.LCD.clear()
|
|
||||||
|
Loading…
Reference in New Issue
Block a user