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

This commit is contained in:
Mike Bell 2022-03-23 00:12:10 +00:00
parent fa2774b114
commit 51b0e472e1
5 changed files with 106 additions and 70 deletions

View File

@ -205,56 +205,21 @@ detail2_title = truncatestring(detail2_title, DETAILS_TEXT_SIZE, TEXT_WIDTH)
detail2_text = truncatestring(detail2_text, DETAILS_TEXT_SIZE, detail2_text = truncatestring(detail2_text, DETAILS_TEXT_SIZE,
TEXT_WIDTH - DETAIL_SPACING - display.measure_text(detail2_title, DETAILS_TEXT_SIZE)) TEXT_WIDTH - DETAIL_SPACING - display.measure_text(detail2_title, DETAILS_TEXT_SIZE))
# Set up the buttons # Show overlay if any of the buttons were pressed to wake up the Badger
button_a = machine.Pin(badger2040.BUTTON_A, machine.Pin.IN, machine.Pin.PULL_DOWN) if (badger2040.pressed_to_wake(badger2040.BUTTON_A) or
button_b = machine.Pin(badger2040.BUTTON_B, machine.Pin.IN, machine.Pin.PULL_DOWN) badger2040.pressed_to_wake(badger2040.BUTTON_B) or
button_c = machine.Pin(badger2040.BUTTON_C, machine.Pin.IN, machine.Pin.PULL_DOWN) badger2040.pressed_to_wake(badger2040.BUTTON_C) or
button_up = machine.Pin(badger2040.BUTTON_UP, machine.Pin.IN, machine.Pin.PULL_DOWN) badger2040.pressed_to_wake(badger2040.BUTTON_UP) or
button_down = machine.Pin(badger2040.BUTTON_DOWN, machine.Pin.IN, machine.Pin.PULL_DOWN) badger2040.pressed_to_wake(badger2040.BUTTON_DOWN)):
# Button handling function
def button(pin):
global show_overlay
if pin == button_a:
show_overlay = True 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)
# ------------------------------ # ------------------------------
# Main program loop # Main program
# ------------------------------ # ------------------------------
draw_badge() draw_badge()
display.update()
while True: if show_overlay:
if show_overlay:
draw_overlay("To change the text, connect Badger2040 to a PC, load up Thonny, and modify badge.txt", 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) WIDTH - OVERLAY_BORDER, HEIGHT - OVERLAY_BORDER, OVERLAY_SPACING, OVERLAY_TEXT_SIZE)
display.update() display.update()
@ -262,6 +227,12 @@ while True:
draw_badge() draw_badge()
display.update() display.update()
show_overlay = False 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()

View File

@ -11,6 +11,39 @@ import launchericons
MAX_BATTERY_VOLTAGE = 4.0 MAX_BATTERY_VOLTAGE = 4.0
MIN_BATTERY_VOLTAGE = 3.2 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 page = 0
font_size = 1 font_size = 1
@ -179,19 +212,9 @@ def render():
display.update() 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): 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: try:
launch(examples[(page * 3) + index][0]) launch(examples[(page * 3) + index][0])
return True return True
@ -241,7 +264,7 @@ display.update_speed(badger2040.UPDATE_FAST)
# Wait for wakeup button to be released # 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(): 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: while True:

View File

@ -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_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_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_invert_obj, Badger2040_invert);
MP_DEFINE_CONST_FUN_OBJ_2(Badger2040_led_obj, Badger2040_led); MP_DEFINE_CONST_FUN_OBJ_2(Badger2040_led_obj, Badger2040_led);
MP_DEFINE_CONST_FUN_OBJ_2(Badger2040_font_obj, Badger2040_font); 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_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 *****/ /***** Binding of Methods *****/
STATIC const mp_rom_map_elem_t Badger2040_locals_dict_table[] = { STATIC const mp_rom_map_elem_t Badger2040_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&Badger2040___del___obj) }, { 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_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_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_invert), MP_ROM_PTR(&Badger2040_invert_obj) },
{ MP_ROM_QSTR(MP_QSTR_led), MP_ROM_PTR(&Badger2040_led_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) }, { 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 *****/ /***** 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___name__), MP_OBJ_NEW_QSTR(MP_QSTR_badger2040) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_Badger2040), (mp_obj_t)&Badger2040_type }, { 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_NORMAL), MP_ROM_INT(0) },
{ MP_ROM_QSTR(MP_QSTR_UPDATE_MEDIUM), MP_ROM_INT(1) }, { MP_ROM_QSTR(MP_QSTR_UPDATE_MEDIUM), MP_ROM_INT(1) },
{ MP_ROM_QSTR(MP_QSTR_UPDATE_FAST), MP_ROM_INT(2) }, { MP_ROM_QSTR(MP_QSTR_UPDATE_FAST), MP_ROM_INT(2) },

View File

@ -3,6 +3,19 @@
#define MP_OBJ_TO_PTR2(o, t) ((t *)(uintptr_t)(o)) #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" { extern "C" {
#include "badger2040.h" #include "badger2040.h"
@ -170,7 +183,11 @@ MICROPY_EVENT_POLL_HOOK
return mp_const_none; 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 // sleep
mp_obj_t Badger2040_invert(mp_obj_t self_in, mp_obj_t invert) { 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; 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
// pressed_to_wake // pressed_to_wake
// wait_for_press - implement in terms of MicroPython! // wait_for_press - implement in terms of MicroPython!

View File

@ -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_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_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_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_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); extern mp_obj_t Badger2040_font(mp_obj_t self_in, mp_obj_t font);
@ -38,3 +40,6 @@ extern mp_obj_t Badger2040_measure_text(size_t n_args, const mp_obj_t *pos_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_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();