From 92e62e0ccbad004b24607bc7709d655c3c4f0446 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Tue, 21 Mar 2023 12:57:47 +0000 Subject: [PATCH] Badger OS: Add keepalive to fix #7. Holding down a button, or pressing a button with the "right" timing would keep the Badger on, despite the 3v3 en pin being turned off. This would result in abrupt power loss when the button is released, causing screen corruption. --- badger_os/examples/badge.py | 4 ++++ badger_os/examples/ebook.py | 4 ++++ badger_os/examples/fonts.py | 4 ++++ badger_os/examples/help.py | 1 + badger_os/examples/image.py | 4 ++++ badger_os/examples/info.py | 1 + badger_os/examples/list.py | 4 ++++ badger_os/examples/net_info.py | 1 + badger_os/examples/news.py | 3 +-- badger_os/examples/qrgen.py | 4 ++++ badger_os/examples/weather.py | 1 + badger_os/launcher.py | 4 ++++ firmware/PIMORONI_BADGER2040/lib/badger2040.py | 11 ++++++++++- firmware/PIMORONI_BADGER2040W/lib/badger2040.py | 11 ++++++++++- 14 files changed, 53 insertions(+), 4 deletions(-) diff --git a/badger_os/examples/badge.py b/badger_os/examples/badge.py index aedf171..c376fd8 100644 --- a/badger_os/examples/badge.py +++ b/badger_os/examples/badge.py @@ -160,6 +160,10 @@ def draw_badge(): draw_badge() while True: + # Sometimes a button press or hold will keep the system + # powered *through* HALT, so latch the power back on. + display.keepalive() + if display.pressed(badger2040.BUTTON_A) or display.pressed(badger2040.BUTTON_B) or display.pressed(badger2040.BUTTON_C) or display.pressed(badger2040.BUTTON_UP) or display.pressed(badger2040.BUTTON_DOWN): badger_os.warning(display, "To change the text, connect Badger2040 to a PC, load up Thonny, and modify badge.txt") time.sleep(4) diff --git a/badger_os/examples/ebook.py b/badger_os/examples/ebook.py index 0ffb75d..cf4394a 100644 --- a/badger_os/examples/ebook.py +++ b/badger_os/examples/ebook.py @@ -189,6 +189,10 @@ def render_page(): state["offsets"] = [] while True: + # Sometimes a button press or hold will keep the system + # powered *through* HALT, so latch the power back on. + display.keepalive() + # Was the next page button pressed? if display.pressed(badger2040.BUTTON_DOWN): state["current_page"] += 1 diff --git a/badger_os/examples/fonts.py b/badger_os/examples/fonts.py index d4329fd..f9d949d 100644 --- a/badger_os/examples/fonts.py +++ b/badger_os/examples/fonts.py @@ -109,6 +109,10 @@ def draw_fonts(): # ------------------------------ while True: + # Sometimes a button press or hold will keep the system + # powered *through* HALT, so latch the power back on. + display.keepalive() + if display.pressed(badger2040.BUTTON_UP): state["selected_font"] -= 1 if state["selected_font"] < 0: diff --git a/badger_os/examples/help.py b/badger_os/examples/help.py index df33f48..890926b 100644 --- a/badger_os/examples/help.py +++ b/badger_os/examples/help.py @@ -38,4 +38,5 @@ # Call halt in a loop, on battery this switches off power. # On USB, the app will exit when A+C is pressed because the launcher picks that up. while True: + display.keepalive() display.halt() diff --git a/badger_os/examples/image.py b/badger_os/examples/image.py index 85fda9d..d721746 100644 --- a/badger_os/examples/image.py +++ b/badger_os/examples/image.py @@ -90,6 +90,10 @@ def show_image(n): while True: + # Sometimes a button press or hold will keep the system + # powered *through* HALT, so latch the power back on. + display.keepalive() + if display.pressed(badger2040.BUTTON_UP): if state["current_image"] > 0: state["current_image"] -= 1 diff --git a/badger_os/examples/info.py b/badger_os/examples/info.py index aa6f430..e592bfd 100644 --- a/badger_os/examples/info.py +++ b/badger_os/examples/info.py @@ -41,4 +41,5 @@ # Call halt in a loop, on battery this switches off power. # On USB, the app will exit when A+C is pressed because the launcher picks that up. while True: + display.keepalive() display.halt() diff --git a/badger_os/examples/list.py b/badger_os/examples/list.py index 5b74125..bf9591c 100644 --- a/badger_os/examples/list.py +++ b/badger_os/examples/list.py @@ -213,6 +213,10 @@ def draw_checkbox(x, y, size, background, foreground, thickness, tick, padding): # ------------------------------ while True: + # Sometimes a button press or hold will keep the system + # powered *through* HALT, so latch the power back on. + display.keepalive() + if len(list_items) > 0: if display.pressed(badger2040.BUTTON_A): if state["current_item"] > 0: diff --git a/badger_os/examples/net_info.py b/badger_os/examples/net_info.py index 0e5ff01..96db200 100644 --- a/badger_os/examples/net_info.py +++ b/badger_os/examples/net_info.py @@ -45,4 +45,5 @@ # Call halt in a loop, on battery this switches off power. # On USB, the app will exit when A+C is pressed because the launcher picks that up. while True: + display.keepalive() display.halt() diff --git a/badger_os/examples/news.py b/badger_os/examples/news.py index 87aa553..db08275 100644 --- a/badger_os/examples/news.py +++ b/badger_os/examples/news.py @@ -176,8 +176,7 @@ def draw_page(): draw_page() -while 1: - +while True: changed = False if button_down.value(): diff --git a/badger_os/examples/qrgen.py b/badger_os/examples/qrgen.py index 8dea8a8..e0f3209 100644 --- a/badger_os/examples/qrgen.py +++ b/badger_os/examples/qrgen.py @@ -112,6 +112,10 @@ def draw_qr_file(n): changed = True while True: + # Sometimes a button press or hold will keep the system + # powered *through* HALT, so latch the power back on. + display.keepalive() + if TOTAL_CODES > 1: if display.pressed(badger2040.BUTTON_UP): if state["current_qr"] > 0: diff --git a/badger_os/examples/weather.py b/badger_os/examples/weather.py index 1e4e97a..c5692fa 100644 --- a/badger_os/examples/weather.py +++ b/badger_os/examples/weather.py @@ -103,4 +103,5 @@ def draw_page(): # Call halt in a loop, on battery this switches off power. # On USB, the app will exit when A+C is pressed because the launcher picks that up. while True: + display.keepalive() display.halt() diff --git a/badger_os/launcher.py b/badger_os/launcher.py index 645cfe6..b54f102 100644 --- a/badger_os/launcher.py +++ b/badger_os/launcher.py @@ -164,6 +164,10 @@ def button(pin): display.set_update_speed(badger2040.UPDATE_FAST) while True: + # Sometimes a button press or hold will keep the system + # powered *through* HALT, so latch the power back on. + display.keepalive() + if display.pressed(badger2040.BUTTON_A): button(badger2040.BUTTON_A) if display.pressed(badger2040.BUTTON_B): diff --git a/firmware/PIMORONI_BADGER2040/lib/badger2040.py b/firmware/PIMORONI_BADGER2040/lib/badger2040.py index ee0a467..b01c971 100644 --- a/firmware/PIMORONI_BADGER2040/lib/badger2040.py +++ b/firmware/PIMORONI_BADGER2040/lib/badger2040.py @@ -51,6 +51,9 @@ WAKEUP_MASK = 0 +enable = machine.Pin(ENABLE_3V3, machine.Pin.OUT) +enable.on() + def is_wireless(): return False @@ -88,9 +91,12 @@ def system_speed(speed): pass +def turn_on(): + enable.on() + + def turn_off(): time.sleep(0.05) - enable = machine.Pin(ENABLE_3V3, machine.Pin.OUT) enable.off() # Simulate an idle state on USB power by blocking # until a button event @@ -150,6 +156,9 @@ def thickness(self, thickness): def halt(self): turn_off() + def keepalive(self): + turn_on() + def pressed(self, button): return BUTTONS[button].value() == (0 if button == BUTTON_USER else 1) or pressed_to_wake_get_once(button) diff --git a/firmware/PIMORONI_BADGER2040W/lib/badger2040.py b/firmware/PIMORONI_BADGER2040W/lib/badger2040.py index e077c1c..6cc1e40 100644 --- a/firmware/PIMORONI_BADGER2040W/lib/badger2040.py +++ b/firmware/PIMORONI_BADGER2040W/lib/badger2040.py @@ -57,6 +57,9 @@ i2c.writeto_mem(0x51, 0x00, b'\x00') # ensure rtc is running (this should be default?) rtc.enable_timer_interrupt(False) +enable = machine.Pin(ENABLE_3V3, machine.Pin.OUT) +enable.on() + def is_wireless(): return True @@ -92,9 +95,12 @@ def system_speed(speed): pass +def turn_on(): + enable.on() + + def turn_off(): time.sleep(0.05) - enable = machine.Pin(ENABLE_3V3, machine.Pin.OUT) enable.off() # Simulate an idle state on USB power by blocking # until an RTC alarm or button event @@ -187,6 +193,9 @@ def thickness(self, thickness): def halt(self): turn_off() + def keepalive(self): + turn_on() + def pressed(self, button): return BUTTONS[button].value() == 1 or pressed_to_wake_get_once(button)