kopia lustrzana https://github.com/pimoroni/pimoroni-pico
Badger2040: Create badger_os utils module.
rodzic
0ab44ef10a
commit
5bd13a5cd1
|
@ -0,0 +1,104 @@
|
|||
"""Keep track of app state in persistent flash storage."""
|
||||
|
||||
import os
|
||||
import gc
|
||||
import machine
|
||||
import badger2040
|
||||
|
||||
STATE_FILE = "appstate.txt"
|
||||
|
||||
|
||||
def get_battery_level():
|
||||
# Battery measurement
|
||||
vbat_adc = machine.ADC(badger2040.PIN_BATTERY)
|
||||
vref_adc = machine.ADC(badger2040.PIN_1V2_REF)
|
||||
vref_en = machine.Pin(badger2040.PIN_VREF_POWER)
|
||||
vref_en.init(machine.Pin.OUT)
|
||||
vref_en.value(0)
|
||||
|
||||
# Enable the onboard voltage reference
|
||||
vref_en.value(1)
|
||||
|
||||
# Calculate the logic supply voltage, as will be lower that the usual 3.3V when running off low batteries
|
||||
vdd = 1.24 * (65535 / vref_adc.read_u16())
|
||||
vbat = (
|
||||
(vbat_adc.read_u16() / 65535) * 3 * vdd
|
||||
) # 3 in this is a gain, not rounding of 3.3V
|
||||
|
||||
# Disable the onboard voltage reference
|
||||
vref_en.value(0)
|
||||
|
||||
# Convert the voltage to a level to display onscreen
|
||||
return vbat
|
||||
|
||||
|
||||
def get_disk_usage():
|
||||
# f_bfree and f_bavail should be the same?
|
||||
# f_files, f_ffree, f_favail and f_flag are unsupported.
|
||||
f_bsize, f_frsize, f_blocks, f_bfree, _, _, _, _, _, f_namemax = os.statvfs("/")
|
||||
|
||||
f_total_size = f_frsize * f_blocks
|
||||
f_total_free = f_bsize * f_bfree
|
||||
f_total_used = f_total_size - f_total_free
|
||||
|
||||
f_used = 100 / f_total_size * f_total_used
|
||||
f_free = 100 / f_total_size * f_total_free
|
||||
|
||||
return f_total_size, f_used, f_free
|
||||
|
||||
|
||||
def state_app():
|
||||
try:
|
||||
with open(STATE_FILE, "r") as f:
|
||||
return f.readline().strip()
|
||||
except OSError:
|
||||
return None
|
||||
|
||||
|
||||
def state_launch():
|
||||
app = state_app()
|
||||
if app is not None:
|
||||
launch("_" + app)
|
||||
|
||||
|
||||
def state_delete():
|
||||
try:
|
||||
os.remove(STATE_FILE)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
def state_save(title, *args):
|
||||
with open(STATE_FILE, "w") as f:
|
||||
f.write("{}\n".format(title))
|
||||
for arg in args:
|
||||
f.write("{}\n".format(arg))
|
||||
|
||||
|
||||
def state_load(title, *defaults):
|
||||
data = []
|
||||
try:
|
||||
with open(STATE_FILE, "r") as f:
|
||||
if f.readline().strip() != title:
|
||||
return defaults
|
||||
for default in defaults:
|
||||
t = type(default)
|
||||
if t is bool:
|
||||
data.append(f.readline().strip() == "True")
|
||||
else:
|
||||
data.append(t(f.readline().strip()))
|
||||
return data
|
||||
except OSError:
|
||||
return defaults
|
||||
|
||||
|
||||
def launch(file):
|
||||
for k in locals().keys():
|
||||
if k not in ("gc", "file", "machine"):
|
||||
del locals()[k]
|
||||
gc.collect()
|
||||
try:
|
||||
__import__(file[1:]) # Try to import _[file] (drop underscore prefix)
|
||||
except ImportError:
|
||||
__import__(file) # Failover to importing [_file]
|
||||
machine.reset() # Exit back to launcher
|
|
@ -3,6 +3,7 @@ import sys
|
|||
import time
|
||||
import badger2040
|
||||
from badger2040 import WIDTH, HEIGHT
|
||||
import badger_os
|
||||
|
||||
|
||||
REAMDE = """
|
||||
|
@ -52,14 +53,6 @@ image = bytearray(int(296 * 128 / 8))
|
|||
current_image = 0
|
||||
show_info = True
|
||||
|
||||
try:
|
||||
with open("appstate.txt", "r") as f:
|
||||
f.readline()
|
||||
current_image = int(f.readline().strip('\n'))
|
||||
show_info = f.readline().strip('\n') == "True"
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
# Draw an overlay box with a given message within it
|
||||
def draw_overlay(message, width, height, line_spacing, text_size):
|
||||
|
@ -127,28 +120,37 @@ if TOTAL_IMAGES == 0:
|
|||
display.update()
|
||||
sys.exit()
|
||||
|
||||
if display.pressed_to_wake(badger2040.BUTTON_UP):
|
||||
if current_image > 0:
|
||||
current_image -= 1
|
||||
if display.pressed_to_wake(badger2040.BUTTON_DOWN):
|
||||
if current_image < TOTAL_IMAGES - 1:
|
||||
current_image += 1
|
||||
if display.pressed_to_wake(badger2040.BUTTON_A):
|
||||
show_info = not show_info
|
||||
if display.pressed_to_wake(badger2040.BUTTON_B) or display.pressed_to_wake(badger2040.BUTTON_C):
|
||||
display.pen(15)
|
||||
display.clear()
|
||||
draw_overlay("To add images connect Badger2040 to a PC, load up Thonny, and see readme.txt in images/", WIDTH - OVERLAY_BORDER, HEIGHT - OVERLAY_BORDER, OVERLAY_SPACING, 0.5)
|
||||
display.update()
|
||||
time.sleep(4)
|
||||
|
||||
show_image(current_image)
|
||||
current_image, show_info = badger_os.state_load("image", 0, True)
|
||||
|
||||
changed = not display.woken()
|
||||
|
||||
|
||||
# Tell launcher to relaunch this app on wake and record state
|
||||
with open("appstate.txt", "w") as f:
|
||||
f.write("image\n")
|
||||
f.write("{}\n{}\n".format(current_image, show_info))
|
||||
while True:
|
||||
if display.pressed(badger2040.BUTTON_UP):
|
||||
if current_image > 0:
|
||||
current_image -= 1
|
||||
changed = True
|
||||
if display.pressed(badger2040.BUTTON_DOWN):
|
||||
if current_image < TOTAL_IMAGES - 1:
|
||||
current_image += 1
|
||||
changed = True
|
||||
if display.pressed(badger2040.BUTTON_A):
|
||||
show_info = not show_info
|
||||
changed = True
|
||||
if display.pressed(badger2040.BUTTON_B) or display.pressed(badger2040.BUTTON_C):
|
||||
display.pen(15)
|
||||
display.clear()
|
||||
draw_overlay("To add images connect Badger2040 to a PC, load up Thonny, and see readme.txt in images/", WIDTH - OVERLAY_BORDER, HEIGHT - OVERLAY_BORDER, OVERLAY_SPACING, 0.5)
|
||||
display.update()
|
||||
print(current_image)
|
||||
time.sleep(4)
|
||||
changed = True
|
||||
|
||||
# Halt the Badger to save power, it will wake up if any of the front buttons are pressed
|
||||
display.halt()
|
||||
if changed:
|
||||
badger_os.state_save("image", current_image, show_info)
|
||||
show_image(current_image)
|
||||
changed = False
|
||||
|
||||
# Halt the Badger to save power, it will wake up if any of the front buttons are pressed
|
||||
display.halt()
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import gc
|
||||
import os
|
||||
import time
|
||||
import math
|
||||
import machine
|
||||
import badger2040
|
||||
from badger2040 import WIDTH
|
||||
import launchericons
|
||||
import badger_os
|
||||
|
||||
# for e.g. 2xAAA batteries, try max 3.4 min 3.0
|
||||
MAX_BATTERY_VOLTAGE = 4.0
|
||||
|
@ -15,33 +14,18 @@ MIN_BATTERY_VOLTAGE = 3.2
|
|||
machine.freq(48000000)
|
||||
|
||||
|
||||
def launch(file):
|
||||
for k in locals().keys():
|
||||
if k not in ("gc", "file", "machine"):
|
||||
del locals()[k]
|
||||
gc.collect()
|
||||
try:
|
||||
__import__(file[1:]) # Try to import _[file] (drop underscore prefix)
|
||||
except ImportError:
|
||||
__import__(file) # Failover to importing [_file]
|
||||
machine.reset() # Exit back to launcher
|
||||
|
||||
|
||||
# Restore previously running app
|
||||
try:
|
||||
# Pressing A and C together at start quits app
|
||||
if badger2040.pressed_to_wake(badger2040.BUTTON_A) and badger2040.pressed_to_wake(badger2040.BUTTON_C):
|
||||
os.remove("appstate.txt")
|
||||
badger_os.state_delete()
|
||||
else:
|
||||
with open("appstate.txt", "r") as f:
|
||||
# Try to launch app
|
||||
launch("_" + f.readline().strip('\n'))
|
||||
badger_os.state_launch()
|
||||
except OSError:
|
||||
pass
|
||||
except ImportError:
|
||||
# Happens if appstate names an unknown app. Delete appstate and reset
|
||||
import os
|
||||
os.remove("appstate.txt")
|
||||
badger_os.state_delete()
|
||||
machine.reset()
|
||||
|
||||
badger2040.clear_pressed_to_wake()
|
||||
|
@ -96,23 +80,6 @@ def map_value(input, in_min, in_max, out_min, out_max):
|
|||
return (((input - in_min) * (out_max - out_min)) / (in_max - in_min)) + out_min
|
||||
|
||||
|
||||
def get_battery_level():
|
||||
# Enable the onboard voltage reference
|
||||
vref_en.value(1)
|
||||
|
||||
# Calculate the logic supply voltage, as will be lower that the usual 3.3V when running off low batteries
|
||||
vdd = 1.24 * (65535 / vref_adc.read_u16())
|
||||
vbat = (
|
||||
(vbat_adc.read_u16() / 65535) * 3 * vdd
|
||||
) # 3 in this is a gain, not rounding of 3.3V
|
||||
|
||||
# Disable the onboard voltage reference
|
||||
vref_en.value(0)
|
||||
|
||||
# Convert the voltage to a level to display onscreen
|
||||
return int(map_value(vbat, MIN_BATTERY_VOLTAGE, MAX_BATTERY_VOLTAGE, 0, 4))
|
||||
|
||||
|
||||
def draw_battery(level, x, y):
|
||||
# Outline
|
||||
display.thickness(1)
|
||||
|
@ -138,17 +105,7 @@ def draw_battery(level, x, y):
|
|||
|
||||
|
||||
def draw_disk_usage(x):
|
||||
# f_bfree and f_bavail should be the same?
|
||||
# f_files, f_ffree, f_favail and f_flag are unsupported.
|
||||
f_bsize, f_frsize, f_blocks, f_bfree, _, _, _, _, _, f_namemax = os.statvfs(
|
||||
"/")
|
||||
|
||||
f_total_size = f_frsize * f_blocks
|
||||
f_total_free = f_bsize * f_bfree
|
||||
f_total_used = f_total_size - f_total_free
|
||||
|
||||
f_used = 100 / f_total_size * f_total_used
|
||||
# f_free = 100 / f_total_size * f_total_free
|
||||
_, f_used, _ = badger_os.get_disk_usage()
|
||||
|
||||
display.image(
|
||||
bytearray(
|
||||
|
@ -207,7 +164,9 @@ def render():
|
|||
display.rectangle(0, 0, WIDTH, 16)
|
||||
display.thickness(1)
|
||||
draw_disk_usage(90)
|
||||
draw_battery(get_battery_level(), WIDTH - 22 - 3, 3)
|
||||
vbat = badger_os.get_battery_level()
|
||||
bat = int(map_value(vbat, MIN_BATTERY_VOLTAGE, MAX_BATTERY_VOLTAGE, 0, 4))
|
||||
draw_battery(bat, WIDTH - 22 - 3, 3)
|
||||
display.pen(15)
|
||||
display.text("badgerOS", 3, 8, 0.4)
|
||||
|
||||
|
@ -218,7 +177,7 @@ def launch_example(index):
|
|||
while button_a.value() or button_b.value() or button_c.value() or button_up.value() or button_down.value():
|
||||
time.sleep(0.01)
|
||||
try:
|
||||
launch(examples[(page * 3) + index][0])
|
||||
badger_os.launch(examples[(page * 3) + index][0])
|
||||
return True
|
||||
except IndexError:
|
||||
return False
|
||||
|
|
|
@ -52,3 +52,4 @@ copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/badge.py _badge)
|
|||
copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/help.py _help)
|
||||
copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/info.py _info)
|
||||
copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/qrgen.py _qrgen)
|
||||
copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/badger_os.py badger_os)
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
namespace {
|
||||
struct Badger2040_WakeUpInit {
|
||||
Badger2040_WakeUpInit()
|
||||
: state(gpio_get_all() & (0x1f << 11)) // Record state of all the front buttons
|
||||
: state(gpio_get_all() & (0x1f << pimoroni::Badger2040::DOWN)) // Record state of front buttons
|
||||
{
|
||||
gpio_set_function(pimoroni::Badger2040::ENABLE_3V3, GPIO_FUNC_SIO);
|
||||
gpio_set_dir(pimoroni::Badger2040::ENABLE_3V3, GPIO_OUT);
|
||||
|
|
Ładowanie…
Reference in New Issue