Skip to content

Commit

Permalink
Fixed USB plug during sleep
Browse files Browse the repository at this point in the history
Which previously didn't prevent the board immediately sleeping again,
meaning the USB stack didn't have long enough to enumerate and for
usb_connected() to return true as a result thereby preventing further
lightsleeps.

Now we explicitly prevent all sleeps for a further 15s
("usb_nosleep_time") after detecting CHARGE_DET going low (indicating
USB power connected) to give the USB stack time to enumerate, after
which point usb_connected() takes over the responsibility for preventing
lightsleep.
  • Loading branch information
tomsci committed May 12, 2022
1 parent 1b617d9 commit c1e70b0
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 19 deletions.
3 changes: 1 addition & 2 deletions modules/app_launcher/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,5 @@ def rotate(self):
self.set_rotation((self.get_rotation() + 90) % 360)

def charge_state_changed(self, charging):
# We'll only hit this if Scheduler.should_sleep() is false
# print(f"Launcher CHARGE_DET charging={charging}")
self.update_title(redraw=True)
get_scheduler().usb_plug_event(charging)
2 changes: 2 additions & 0 deletions modules/buttons.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ def __init__(self):
self._autorepeating_button = None
self._isr_flag = False
self._rotation = tidal.get_display_rotation()
# This doesn't seem like the best place to put this, but I can't think of a better offhand
self.on_up_down(tidal.CHARGE_DET, get_scheduler().usb_plug_event)

def is_active(self):
return _current == self
Expand Down
35 changes: 18 additions & 17 deletions modules/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,7 @@ class Scheduler:
def __init__(self):
self._timers = []
self.no_sleep_before = time.ticks_ms() + (settings.get("boot_nosleep_time", 15) * 1000)
# Could do this more directly, but this is easy
import buttons
self._wake_lcd_buttons = buttons.Buttons()
for button in tidal.ALL_BUTTONS:
# We don't need these button presses to do anything, they just have to exist
self._wake_lcd_buttons.on_press(button, lambda: 0)
# CHARGE_DET isn't a button, but Buttons.on_up_down works for any GPIO
# in a way compatible with lightsleep, so it's convenient
self._wake_lcd_buttons.on_up_down(tidal.CHARGE_DET, self._usb_plug_event)
self._wake_lcd_buttons = None

def switch_app(self, app):
"""Asynchronously switch to the specified app."""
Expand Down Expand Up @@ -94,7 +86,6 @@ def main(self, initial_app):
self.enter()

def enter(self):
import buttons
first_time = True
self._level += 1
enter_level = self._level
Expand Down Expand Up @@ -148,7 +139,7 @@ def enter(self):
# doesn't get passed to the app, and (b) so that any button
# wakes the screen, even ones the app hasn't registered an
# interrupt for.
self._wake_lcd_buttons.activate()
self.wake_lcd_buttons.activate()

wakeup_cause = tidal_helpers.lightsleep(t)
# print(f"Returned from lightsleep reason={wakeup_cause}")
Expand Down Expand Up @@ -189,18 +180,28 @@ def reset_inactivity(self):
self._last_activity_time = time.ticks_ms()
tidal.lcd_power_on()

def _usb_plug_event(self, charging):
# We don't actually have to do anything here, the side effect of Buttons
# calling reset_inactivity is all we needed
# print(f"CHARGE_DET charging={charging}")
pass
@property
def wake_lcd_buttons(self):
if self._wake_lcd_buttons is None:
import buttons
self._wake_lcd_buttons = buttons.Buttons()
for button in tidal.ALL_BUTTONS:
# We don't need these button presses to do anything, they just have to exist
self._wake_lcd_buttons.on_press(button, lambda: 0)
return self._wake_lcd_buttons

def usb_plug_event(self, charging):
print(f"CHARGE_DET charging={charging}")
if charging:
# Prevent sleep again to give USB chance to enumerate
self.no_sleep_before = time.ticks_ms() + (settings.get("usb_nosleep_time", 15) * 1000)

def get_inactivity_time(self):
return settings.get("inactivity_time", 30) * 1000

def check_for_interrupts(self):
"""Check for any pending interrupts and schedule uasyncio tasks for them."""
found = self._wake_lcd_buttons.check_for_interrupts()
found = self.wake_lcd_buttons.check_for_interrupts()
if self._current_app and self._current_app.check_for_interrupts():
found = True
t = time.ticks_ms()
Expand Down

0 comments on commit c1e70b0

Please sign in to comment.