Add ability to halt the Badger from Micropython and get wake button presses. Change badge app to halt when image displayed

MichaelBell-battery-improvements
Mike Bell 2022-03-23 00:12:10 +00:00
rodzic fa2774b114
commit 51b0e472e1
5 zmienionych plików z 106 dodań i 70 usunięć

Wyświetl plik

@ -205,63 +205,34 @@ detail2_title = truncatestring(detail2_title, DETAILS_TEXT_SIZE, TEXT_WIDTH)
detail2_text = truncatestring(detail2_text, DETAILS_TEXT_SIZE,
TEXT_WIDTH - DETAIL_SPACING - display.measure_text(detail2_title, DETAILS_TEXT_SIZE))
# Set up the buttons
button_a = machine.Pin(badger2040.BUTTON_A, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_b = machine.Pin(badger2040.BUTTON_B, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_c = machine.Pin(badger2040.BUTTON_C, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_up = machine.Pin(badger2040.BUTTON_UP, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_down = machine.Pin(badger2040.BUTTON_DOWN, machine.Pin.IN, machine.Pin.PULL_DOWN)
# Button handling function
def button(pin):
global show_overlay
if pin == button_a:
show_overlay = True
return
if pin == button_b:
show_overlay = True
return
if pin == button_c:
show_overlay = True
return
if pin == button_up:
show_overlay = True
return
if pin == button_down:
show_overlay = True
return
# Register the button handling function with the buttons
button_a.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
button_b.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
button_c.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
button_up.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
button_down.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
# Show overlay if any of the buttons were pressed to wake up the Badger
if (badger2040.pressed_to_wake(badger2040.BUTTON_A) or
badger2040.pressed_to_wake(badger2040.BUTTON_B) or
badger2040.pressed_to_wake(badger2040.BUTTON_C) or
badger2040.pressed_to_wake(badger2040.BUTTON_UP) or
badger2040.pressed_to_wake(badger2040.BUTTON_DOWN)):
show_overlay = True
# ------------------------------
# Main program loop
# Main program
# ------------------------------
draw_badge()
display.update()
while True:
if show_overlay:
draw_overlay("To change the text, connect Badger2040 to a PC, load up Thonny, and modify badge.txt",
WIDTH - OVERLAY_BORDER, HEIGHT - OVERLAY_BORDER, OVERLAY_SPACING, OVERLAY_TEXT_SIZE)
display.update()
time.sleep(4)
if show_overlay:
draw_overlay("To change the text, connect Badger2040 to a PC, load up Thonny, and modify badge.txt",
WIDTH - OVERLAY_BORDER, HEIGHT - OVERLAY_BORDER, OVERLAY_SPACING, OVERLAY_TEXT_SIZE)
display.update()
time.sleep(4)
draw_badge()
display.update()
show_overlay = False
draw_badge()
display.update()
else:
display.update()
time.sleep(0.1)
# Tell launcher to relaunch this app on wake
with open("appstate.txt", "w") as f:
f.write("badge\n")
# Halt the Badger to save power, it will wake up if any of the front buttons are pressed
display.halt()

Wyświetl plik

@ -11,6 +11,39 @@ import launchericons
MAX_BATTERY_VOLTAGE = 4.0
MIN_BATTERY_VOLTAGE = 3.2
# Reduce clock speed to 48MHz, that's fast enough!
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")
else:
with open("appstate.txt", "r") as f:
# Try to launch app
launch("_" + f.readline().strip('\n'))
except OSError:
pass
except ImportError:
# Happens if appstate names an unknown app. Delete appstate and reset
import os
os.remove("appstate.txt")
machine.reset()
badger2040.clear_pressed_to_wake()
page = 0
font_size = 1
@ -179,19 +212,9 @@ def render():
display.update()
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
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])
return True
@ -241,7 +264,7 @@ display.update_speed(badger2040.UPDATE_FAST)
# Wait for wakeup button to be released
while button_a.value() or button_b.value() or button_c.value() or button_up.value() or button_down.value():
pass
time.sleep(0.01)
while True:

Wyświetl plik

@ -9,6 +9,8 @@ MP_DEFINE_CONST_FUN_OBJ_1(Badger2040_is_busy_obj, Badger2040_is_busy);
MP_DEFINE_CONST_FUN_OBJ_1(Badger2040_update_obj, Badger2040_update);
MP_DEFINE_CONST_FUN_OBJ_KW(Badger2040_partial_update_obj, 4, Badger2040_partial_update);
MP_DEFINE_CONST_FUN_OBJ_1(Badger2040_halt_obj, Badger2040_halt);
MP_DEFINE_CONST_FUN_OBJ_2(Badger2040_invert_obj, Badger2040_invert);
MP_DEFINE_CONST_FUN_OBJ_2(Badger2040_led_obj, Badger2040_led);
MP_DEFINE_CONST_FUN_OBJ_2(Badger2040_font_obj, Badger2040_font);
@ -32,6 +34,9 @@ MP_DEFINE_CONST_FUN_OBJ_KW(Badger2040_measure_glyph_obj, 2, Badger2040_measure_g
MP_DEFINE_CONST_FUN_OBJ_3(Badger2040_command_obj, Badger2040_command);
MP_DEFINE_CONST_FUN_OBJ_1(Badger2040_pressed_to_wake_obj, Badger2040_pressed_to_wake);
MP_DEFINE_CONST_FUN_OBJ_0(Badger2040_clear_pressed_to_wake_obj, Badger2040_clear_pressed_to_wake);
/***** Binding of Methods *****/
STATIC const mp_rom_map_elem_t Badger2040_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&Badger2040___del___obj) },
@ -40,6 +45,8 @@ STATIC const mp_rom_map_elem_t Badger2040_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&Badger2040_update_obj) },
{ MP_ROM_QSTR(MP_QSTR_partial_update), MP_ROM_PTR(&Badger2040_partial_update_obj) },
{ MP_ROM_QSTR(MP_QSTR_halt), MP_ROM_PTR(&Badger2040_halt_obj) },
{ MP_ROM_QSTR(MP_QSTR_invert), MP_ROM_PTR(&Badger2040_invert_obj) },
{ MP_ROM_QSTR(MP_QSTR_led), MP_ROM_PTR(&Badger2040_led_obj) },
{ MP_ROM_QSTR(MP_QSTR_font), MP_ROM_PTR(&Badger2040_font_obj) },
@ -78,10 +85,13 @@ const mp_obj_type_t Badger2040_type = {
/***** Globals Table *****/
STATIC const mp_map_elem_t badger2040_globals_table[] = {
STATIC const mp_rom_map_elem_t badger2040_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_badger2040) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_Badger2040), (mp_obj_t)&Badger2040_type },
{ MP_ROM_QSTR(MP_QSTR_pressed_to_wake), MP_ROM_PTR(&Badger2040_pressed_to_wake_obj) },
{ MP_ROM_QSTR(MP_QSTR_clear_pressed_to_wake), MP_ROM_PTR(&Badger2040_clear_pressed_to_wake_obj) },
{ MP_ROM_QSTR(MP_QSTR_UPDATE_NORMAL), MP_ROM_INT(0) },
{ MP_ROM_QSTR(MP_QSTR_UPDATE_MEDIUM), MP_ROM_INT(1) },
{ MP_ROM_QSTR(MP_QSTR_UPDATE_FAST), MP_ROM_INT(2) },
@ -121,4 +131,4 @@ const mp_obj_module_t badger2040_user_cmodule = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&mp_module_badger2040_globals,
};
MP_REGISTER_MODULE(MP_QSTR_badger2040, badger2040_user_cmodule, MODULE_BADGER2040_ENABLED);
MP_REGISTER_MODULE(MP_QSTR_badger2040, badger2040_user_cmodule, MODULE_BADGER2040_ENABLED);

Wyświetl plik

@ -3,6 +3,19 @@
#define MP_OBJ_TO_PTR2(o, t) ((t *)(uintptr_t)(o))
namespace {
struct Badger2040_ButtonStateOnWake {
Badger2040_ButtonStateOnWake()
: state(gpio_get_all())
{}
uint32_t get() const { return state; }
void clear() { state = 0; }
private:
uint32_t state;
} button_wake_state __attribute__ ((init_priority (101)));
};
extern "C" {
#include "badger2040.h"
@ -170,7 +183,11 @@ MICROPY_EVENT_POLL_HOOK
return mp_const_none;
}
// halt
mp_obj_t Badger2040_halt(mp_obj_t self_in) {
_Badger2040_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Badger2040_obj_t);
self->badger2040->halt();
return mp_const_none;
}
// sleep
mp_obj_t Badger2040_invert(mp_obj_t self_in, mp_obj_t invert) {
@ -210,6 +227,16 @@ mp_obj_t Badger2040_pressed(mp_obj_t self_in, mp_obj_t button) {
return state ? mp_const_true : mp_const_false;
}
mp_obj_t Badger2040_pressed_to_wake(mp_obj_t button) {
bool state = (button_wake_state.get() >> mp_obj_get_int(button)) & 1;
return state ? mp_const_true : mp_const_false;
}
mp_obj_t Badger2040_clear_pressed_to_wake() {
button_wake_state.clear();
return mp_const_none;
}
// pressed
// pressed_to_wake
// wait_for_press - implement in terms of MicroPython!
@ -467,4 +494,4 @@ mp_obj_t Badger2040_measure_glyph(size_t n_args, const mp_obj_t *pos_args, mp_ma
return mp_obj_new_int(self->badger2040->measure_glyph(c, scale));
}
}
}

Wyświetl plik

@ -15,6 +15,8 @@ extern mp_obj_t Badger2040_update_speed(mp_obj_t self_in, mp_obj_t speed);
extern mp_obj_t Badger2040_update(mp_obj_t self_in);
extern mp_obj_t Badger2040_partial_update(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
extern mp_obj_t Badger2040_halt(mp_obj_t self_in);
extern mp_obj_t Badger2040_invert(mp_obj_t self_in, mp_obj_t invert);
extern mp_obj_t Badger2040_led(mp_obj_t self_in, mp_obj_t brightness);
extern mp_obj_t Badger2040_font(mp_obj_t self_in, mp_obj_t font);
@ -37,4 +39,7 @@ extern mp_obj_t Badger2040_glyph(size_t n_args, const mp_obj_t *pos_args, mp_map
extern mp_obj_t Badger2040_measure_text(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
extern mp_obj_t Badger2040_measure_glyph(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
extern mp_obj_t Badger2040_command(mp_obj_t self_in, mp_obj_t reg, mp_obj_t data);
extern mp_obj_t Badger2040_command(mp_obj_t self_in, mp_obj_t reg, mp_obj_t data);
extern mp_obj_t Badger2040_pressed_to_wake(mp_obj_t button);
extern mp_obj_t Badger2040_clear_pressed_to_wake();