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 time
|
||||||
import badger2040
|
import badger2040
|
||||||
from badger2040 import WIDTH, HEIGHT
|
from badger2040 import WIDTH, HEIGHT
|
||||||
|
import badger_os
|
||||||
|
|
||||||
|
|
||||||
REAMDE = """
|
REAMDE = """
|
||||||
|
@ -52,14 +53,6 @@ image = bytearray(int(296 * 128 / 8))
|
||||||
current_image = 0
|
current_image = 0
|
||||||
show_info = True
|
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
|
# Draw an overlay box with a given message within it
|
||||||
def draw_overlay(message, width, height, line_spacing, text_size):
|
def draw_overlay(message, width, height, line_spacing, text_size):
|
||||||
|
@ -127,28 +120,37 @@ if TOTAL_IMAGES == 0:
|
||||||
display.update()
|
display.update()
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
if display.pressed_to_wake(badger2040.BUTTON_UP):
|
|
||||||
|
current_image, show_info = badger_os.state_load("image", 0, True)
|
||||||
|
|
||||||
|
changed = not display.woken()
|
||||||
|
|
||||||
|
|
||||||
|
while True:
|
||||||
|
if display.pressed(badger2040.BUTTON_UP):
|
||||||
if current_image > 0:
|
if current_image > 0:
|
||||||
current_image -= 1
|
current_image -= 1
|
||||||
if display.pressed_to_wake(badger2040.BUTTON_DOWN):
|
changed = True
|
||||||
|
if display.pressed(badger2040.BUTTON_DOWN):
|
||||||
if current_image < TOTAL_IMAGES - 1:
|
if current_image < TOTAL_IMAGES - 1:
|
||||||
current_image += 1
|
current_image += 1
|
||||||
if display.pressed_to_wake(badger2040.BUTTON_A):
|
changed = True
|
||||||
|
if display.pressed(badger2040.BUTTON_A):
|
||||||
show_info = not show_info
|
show_info = not show_info
|
||||||
if display.pressed_to_wake(badger2040.BUTTON_B) or display.pressed_to_wake(badger2040.BUTTON_C):
|
changed = True
|
||||||
|
if display.pressed(badger2040.BUTTON_B) or display.pressed(badger2040.BUTTON_C):
|
||||||
display.pen(15)
|
display.pen(15)
|
||||||
display.clear()
|
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)
|
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()
|
display.update()
|
||||||
|
print(current_image)
|
||||||
time.sleep(4)
|
time.sleep(4)
|
||||||
|
changed = True
|
||||||
|
|
||||||
|
if changed:
|
||||||
|
badger_os.state_save("image", current_image, show_info)
|
||||||
show_image(current_image)
|
show_image(current_image)
|
||||||
|
changed = False
|
||||||
|
|
||||||
# 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))
|
|
||||||
|
|
||||||
# Halt the Badger to save power, it will wake up if any of the front buttons are pressed
|
# Halt the Badger to save power, it will wake up if any of the front buttons are pressed
|
||||||
display.halt()
|
display.halt()
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import gc
|
|
||||||
import os
|
|
||||||
import time
|
import time
|
||||||
import math
|
import math
|
||||||
import machine
|
import machine
|
||||||
import badger2040
|
import badger2040
|
||||||
from badger2040 import WIDTH
|
from badger2040 import WIDTH
|
||||||
import launchericons
|
import launchericons
|
||||||
|
import badger_os
|
||||||
|
|
||||||
# for e.g. 2xAAA batteries, try max 3.4 min 3.0
|
# for e.g. 2xAAA batteries, try max 3.4 min 3.0
|
||||||
MAX_BATTERY_VOLTAGE = 4.0
|
MAX_BATTERY_VOLTAGE = 4.0
|
||||||
|
@ -15,33 +14,18 @@ MIN_BATTERY_VOLTAGE = 3.2
|
||||||
machine.freq(48000000)
|
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
|
# Restore previously running app
|
||||||
try:
|
try:
|
||||||
# Pressing A and C together at start quits app
|
# 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):
|
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:
|
else:
|
||||||
with open("appstate.txt", "r") as f:
|
badger_os.state_launch()
|
||||||
# Try to launch app
|
|
||||||
launch("_" + f.readline().strip('\n'))
|
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# Happens if appstate names an unknown app. Delete appstate and reset
|
# Happens if appstate names an unknown app. Delete appstate and reset
|
||||||
import os
|
badger_os.state_delete()
|
||||||
os.remove("appstate.txt")
|
|
||||||
machine.reset()
|
machine.reset()
|
||||||
|
|
||||||
badger2040.clear_pressed_to_wake()
|
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
|
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):
|
def draw_battery(level, x, y):
|
||||||
# Outline
|
# Outline
|
||||||
display.thickness(1)
|
display.thickness(1)
|
||||||
|
@ -138,17 +105,7 @@ def draw_battery(level, x, y):
|
||||||
|
|
||||||
|
|
||||||
def draw_disk_usage(x):
|
def draw_disk_usage(x):
|
||||||
# f_bfree and f_bavail should be the same?
|
_, f_used, _ = badger_os.get_disk_usage()
|
||||||
# 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
|
|
||||||
|
|
||||||
display.image(
|
display.image(
|
||||||
bytearray(
|
bytearray(
|
||||||
|
@ -207,7 +164,9 @@ def render():
|
||||||
display.rectangle(0, 0, WIDTH, 16)
|
display.rectangle(0, 0, WIDTH, 16)
|
||||||
display.thickness(1)
|
display.thickness(1)
|
||||||
draw_disk_usage(90)
|
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.pen(15)
|
||||||
display.text("badgerOS", 3, 8, 0.4)
|
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():
|
while button_a.value() or button_b.value() or button_c.value() or button_up.value() or button_down.value():
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
try:
|
try:
|
||||||
launch(examples[(page * 3) + index][0])
|
badger_os.launch(examples[(page * 3) + index][0])
|
||||||
return True
|
return True
|
||||||
except IndexError:
|
except IndexError:
|
||||||
return False
|
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}/help.py _help)
|
||||||
copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/info.py _info)
|
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}/qrgen.py _qrgen)
|
||||||
|
copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/badger_os.py badger_os)
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
namespace {
|
namespace {
|
||||||
struct Badger2040_WakeUpInit {
|
struct Badger2040_WakeUpInit {
|
||||||
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_function(pimoroni::Badger2040::ENABLE_3V3, GPIO_FUNC_SIO);
|
||||||
gpio_set_dir(pimoroni::Badger2040::ENABLE_3V3, GPIO_OUT);
|
gpio_set_dir(pimoroni::Badger2040::ENABLE_3V3, GPIO_OUT);
|
||||||
|
|
Ładowanie…
Reference in New Issue