diff --git a/python_payload/apps/demo_sparabo.py b/python_payload/apps/demo_sparabo.py
index fcf6648bb4f96e4c4ef12d33d34c689e079275ba..739826cb134b91a51ecce76d29d1c6fa8315ae5c 100644
--- a/python_payload/apps/demo_sparabo.py
+++ b/python_payload/apps/demo_sparabo.py
@@ -21,7 +21,9 @@ class AppSparabo(application.Application):
         self.synth.decay_ms(250)
 
         print("here")
-        self.sequencer = event.Sequence(bpm=160, steps=8, action=self.on_step, loop=True)
+        self.sequencer = event.Sequence(
+            bpm=160, steps=8, action=self.on_step, loop=True
+        )
         self.sequencer.start()
         if self.sequencer.repeat_event:
             self.add_event(self.sequencer.repeat_event)
@@ -34,7 +36,7 @@ class AppSparabo(application.Application):
             synth.start()
 
         self.x, self.y = ui.xy_from_polar(90, -2 * math.pi / 8 * data["step"] + math.pi)
-        self.step = data['step']
+        self.step = data["step"]
 
     def on_draw(self, ctx):
         x, y = self.x, self.y
diff --git a/python_payload/apps/flow3r/menu_main.py b/python_payload/apps/flow3r/menu_main.py
index ac2a47aacfc62a93e8ebf1a9b44fb649f450fdbd..308c92645c8da9d9f9ec07a2d1175b26ddeadc73 100644
--- a/python_payload/apps/flow3r/menu_main.py
+++ b/python_payload/apps/flow3r/menu_main.py
@@ -8,7 +8,6 @@ from apps.flow3r import menu_settings, menu_tinysynth, menu_crazysynth
 import time
 
 
-
 def get_menu(app):
     menu_main = menu.Menu("flow3r", has_back=False)
     menu_badge = menu.Menu("badge")
diff --git a/python_payload/apps/flow3r/menu_tinysynth.py b/python_payload/apps/flow3r/menu_tinysynth.py
index 1e725d2e76df558cdb27c6a61d36a3e06afcbc24..b534a941e023062a530bbc922525a0c6a764aa01 100644
--- a/python_payload/apps/flow3r/menu_tinysynth.py
+++ b/python_payload/apps/flow3r/menu_tinysynth.py
@@ -6,6 +6,7 @@ from st3m.system import hardware, audio
 synth = tinysynth(440)
 synth.sustain(1)
 
+
 def set_play(value):
     print("set_controls_overlay")
     if value:
diff --git a/python_payload/apps/harmonic_demo.py b/python_payload/apps/harmonic_demo.py
index d8c361a2fe99e2d6d70a343b374949b4cf412e84..9301bea890c28e7aa919d0011f826947c3a11676 100644
--- a/python_payload/apps/harmonic_demo.py
+++ b/python_payload/apps/harmonic_demo.py
@@ -20,17 +20,15 @@ class HarmonicApp(Application):
         self.color_intensity = 0
         self.chord_index = None
         self.chord = None
-        self.synths = [
-            tinysynth(440) for i in range(15)
-        ]
+        self.synths = [tinysynth(440) for i in range(15)]
         for i, synth in enumerate(self.synths):
             synth.decay_ms(100)
             synth.sustain(0.5)
-            if(i<5):
+            if i < 5:
                 synth.waveform(1)
                 synth.volume(0.5)
                 synth.release_ms(1200)
-            elif(i<10):
+            elif i < 10:
                 synth.waveform(1)
                 synth.attack_ms(300)
                 synth.volume(0.1)
@@ -75,18 +73,18 @@ class HarmonicApp(Application):
                 else:
                     k = int(i / 2)
                     self.synths[k].tone(self.chord[k])
-                    self.synths[k+5].tone(12+self.chord[k])
-                    self.synths[k+10].tone(7+self.chord[k])
+                    self.synths[k + 5].tone(12 + self.chord[k])
+                    self.synths[k + 10].tone(7 + self.chord[k])
                     self.synths[k].start()
-                    self.synths[k+5].start()
-                    self.synths[k+10].start()
+                    self.synths[k + 5].start()
+                    self.synths[k + 10].start()
                     self.color_intensity = 1.0
             else:
-                if (1+i) % 2:
+                if (1 + i) % 2:
                     k = int(i / 2)
                     self.synths[k].stop()
-                    self.synths[k+5].stop()
-                    self.synths[k+10].stop()
+                    self.synths[k + 5].stop()
+                    self.synths[k + 10].stop()
 
 
 app = HarmonicApp("harmonic")
diff --git a/python_payload/main_st4m.py b/python_payload/main_st4m.py
index 9aaaddfa9d943e7210dc1534515a54ff14999969..4e2bd30ed4d34a9002a544553e0d60a4e64ccce7 100644
--- a/python_payload/main_st4m.py
+++ b/python_payload/main_st4m.py
@@ -11,7 +11,13 @@ import st4m
 
 from st4m.goose import Optional, List, ABCBase, abstractmethod
 from st4m.ui.view import View, ViewManager, ViewTransitionBlend
-from st4m.ui.menu import MenuItem, MenuController, MenuItemBack, MenuItemForeground, MenuItemNoop
+from st4m.ui.menu import (
+    MenuItem,
+    MenuController,
+    MenuItemBack,
+    MenuItemForeground,
+    MenuItemNoop,
+)
 from st4m import Responder, InputState, Ctx
 
 import math, hardware
@@ -32,6 +38,7 @@ class USBIcon(Responder):
     """
     Found in the bargain bin at an Aldi Süd.
     """
+
     def draw(self, ctx: Ctx) -> None:
         ctx.gray(1.0)
         ctx.arc(-90, 0, 20, 0, 6.28, 0).fill()
@@ -41,7 +48,7 @@ class USBIcon(Responder):
         ctx.move_to(-50, 0).line_to(-10, -40).line_to(20, -40).stroke()
         ctx.arc(20, -40, 15, 0, 6.28, 0).fill()
         ctx.move_to(-30, 0).line_to(10, 40).line_to(40, 40).stroke()
-        ctx.rectangle(40-15, 40-15, 30, 30).fill()
+        ctx.rectangle(40 - 15, 40 - 15, 30, 30).fill()
 
     def think(self, ins: InputState, delta_ms: int) -> None:
         pass
@@ -63,6 +70,7 @@ class Sun(Responder):
     """
     A rotating sun widget.
     """
+
     def __init__(self) -> None:
         self.x = 0.0
         self.y = 0.0
@@ -74,12 +82,11 @@ class Sun(Responder):
         pass
 
     def draw(self, ctx: Ctx) -> None:
-
         nrays = 10
         angle_per_ray = 6.28 / nrays
         for i in range(nrays):
             angle = i * angle_per_ray + self.ts / 4000
-            angle %= 3.14159*2
+            angle %= 3.14159 * 2
 
             if angle > 2 and angle < 4:
                 continue
@@ -108,8 +115,8 @@ class MainMenu(MenuController):
     """
 
     __slots__ = (
-        '_ts',
-        '_sun',
+        "_ts",
+        "_sun",
     )
 
     def __init__(self, items: List[MenuItem], vm: ViewManager) -> None:
@@ -122,7 +129,9 @@ class MainMenu(MenuController):
         self._sun.think(ins, delta_ms)
         self._ts += delta_ms
 
-    def _draw_text_angled(self, ctx: Ctx, text: str, angle: float, activity: float) -> None:
+    def _draw_text_angled(
+        self, ctx: Ctx, text: str, angle: float, activity: float
+    ) -> None:
         size = lerp(20, 40, activity)
         color = lerp(0, 1, activity)
         if color < 0.01:
@@ -137,7 +146,7 @@ class MainMenu(MenuController):
     def draw(self, ctx: Ctx) -> None:
         ctx.gray(0)
         ctx.rectangle(-120, -120, 240, 240).fill()
-        
+
         self._sun.draw(ctx)
 
         ctx.font_size = 40
@@ -150,13 +159,14 @@ class MainMenu(MenuController):
 
         for ix, item in enumerate(self._items):
             rot = (ix - current) * angle_per_item
-            self._draw_text_angled(ctx, item.label(), rot, 1-abs(rot))
-    
+            self._draw_text_angled(ctx, item.label(), rot, 1 - abs(rot))
+
 
 class SimpleMenu(MenuController):
     """
     A simple line-by-line menu.
     """
+
     def draw(self, ctx: Ctx) -> None:
         ctx.gray(0)
         ctx.rectangle(-120, -120, 240, 240).fill()
@@ -174,26 +184,35 @@ class SimpleMenu(MenuController):
             ctx.move_to(0, offs).text(item.label())
 
 
-menu_music = SimpleMenu([
-    MenuItemBack(),
-    MenuItemNoop("Harmonic"),
-    MenuItemNoop("Melodic"),
-    MenuItemNoop("TinySynth"),
-    MenuItemNoop("CrazySynth"),
-    MenuItemNoop("Sequencer"),
-], vm)
-
-menu_apps = SimpleMenu([
-    MenuItemBack(),
-    MenuItemNoop("captouch"),
-    MenuItemNoop("worms"),
-], vm)
-
-menu_main = MainMenu([
-    MenuItemForeground("Music", menu_music),
-    MenuItemForeground("Apps", menu_apps),
-    MenuItemNoop("Settings"),
-], vm)
+menu_music = SimpleMenu(
+    [
+        MenuItemBack(),
+        MenuItemNoop("Harmonic"),
+        MenuItemNoop("Melodic"),
+        MenuItemNoop("TinySynth"),
+        MenuItemNoop("CrazySynth"),
+        MenuItemNoop("Sequencer"),
+    ],
+    vm,
+)
+
+menu_apps = SimpleMenu(
+    [
+        MenuItemBack(),
+        MenuItemNoop("captouch"),
+        MenuItemNoop("worms"),
+    ],
+    vm,
+)
+
+menu_main = MainMenu(
+    [
+        MenuItemForeground("Music", menu_music),
+        MenuItemForeground("Apps", menu_apps),
+        MenuItemNoop("Settings"),
+    ],
+    vm,
+)
 
 vm.push(menu_main)
 
@@ -207,7 +226,7 @@ class Viewport(Responder):
 
     def think(self, ins: InputState, delta_ms: int) -> None:
         self.vm.think(ins, delta_ms)
-        
+
         self.visible = []
         usb = hardware.usb_connected()
         console = hardware.usb_console_active()
@@ -215,7 +234,7 @@ class Viewport(Responder):
             console = False
         if usb:
             self.visible.append(self.usb)
-        #if console:
+        # if console:
         #    self.visible.append(self.repl)
 
         for v in self.visible:
diff --git a/python_payload/mypystubs/badge_link.pyi b/python_payload/mypystubs/badge_link.pyi
index cab12382688bbb3707c2c7149ee8e5c6b21da9df..7e31d61d64d615ee3204a51b82779da99753deea 100644
--- a/python_payload/mypystubs/badge_link.pyi
+++ b/python_payload/mypystubs/badge_link.pyi
@@ -38,8 +38,8 @@ class Pin(Protocol):
     """
     TODO(q3k): properly define in machine.pyi
     """
-    pass
 
+    pass
 
 class JackPin(Protocol):
     @property
@@ -51,7 +51,6 @@ class JackPin(Protocol):
         badgelink mode.
         """
         ...
-
     def enable(self) -> bool:
         """
         Enable badgelink on this jack, on both ring and tip connectors.
@@ -67,13 +66,11 @@ class JackPin(Protocol):
         currently plugged in (as a safety measure).
         """
         ...
-
     def disable(self) -> None:
         """
         Disable badgelink on this jack, returning it into audio mode.
         """
         ...
-
     def active(self) -> bool:
         """
         Returns true if this pin is currently enabled for badgelink, false if
@@ -100,7 +97,6 @@ class Jack(Protocol):
         individually enabled using the .pin.enable/.pin.disable methods.
         """
         ...
-
     def disable(self) -> None:
         """
         Disable badgelink on this jack, returning it into audio mode.
@@ -109,7 +105,6 @@ class Jack(Protocol):
         individually disabled using the .pin.enable/.pin.disable methods.
         """
         ...
-
     def active(self) -> bool:
         """
         Returns true if this jack is currently fully enabled for badgelink,
@@ -119,7 +114,6 @@ class Jack(Protocol):
         false.
         """
         ...
-
     @property
     def tip(self) -> JackPin:
         """
@@ -130,7 +124,6 @@ class Jack(Protocol):
         badge link on this pin only.
         """
         ...
-
     @property
     def ring(self) -> JackPin:
         """
@@ -143,4 +136,4 @@ class Jack(Protocol):
         ...
 
 left: Jack
-right: JackKhizqrU9ANxlu5sP
\ No newline at end of file
+right: JackKhizqrU9ANxlu5sP
diff --git a/python_payload/mypystubs/captouch.pyi b/python_payload/mypystubs/captouch.pyi
index 6a4d4c07b95c07d0ffa6cea0331d0bdecd1da304..1b8822d50dfc0ac389b898d2a048bc5d09fa3f9c 100644
--- a/python_payload/mypystubs/captouch.pyi
+++ b/python_payload/mypystubs/captouch.pyi
@@ -1,6 +1,5 @@
 from typing import Protocol, List
 
-
 class CaptouchPetalPadsState(Protocol):
     """
     Current state of pads on a captouch petal.
@@ -15,21 +14,18 @@ class CaptouchPetalPadsState(Protocol):
         True if the petals's tip is currently touched.
         """
         ...
-    
     @property
     def base(self) -> bool:
         """
         True if the petal's base is currently touched.
         """
         ...
-
     @property
     def cw(self) -> bool:
         """
         True if the petal's clockwise pad is currently touched.
         """
         ...
-
     @property
     def ccw(self) -> bool:
         """
@@ -37,7 +33,6 @@ class CaptouchPetalPadsState(Protocol):
         """
         ...
 
-
 class CaptouchPetalState(Protocol):
     @property
     def pressed(self) -> bool:
@@ -45,21 +40,18 @@ class CaptouchPetalState(Protocol):
         True if any of the petal's pads is currently touched.
         """
         ...
-
     @property
     def top(self) -> bool:
         """
         True if this is a top petal.
         """
         ...
-
     @property
     def bottom(self) -> bool:
         """
         True if this is a bottom petal.
         """
         ...
-
     @property
     def pads(self) -> CaptouchPetalPadsState:
         """
@@ -67,11 +59,11 @@ class CaptouchPetalState(Protocol):
         """
         ...
 
-
 class CaptouchState(Protocol):
     """
     State of captouch sensors, captured at some time.
     """
+
     @property
     def petals(self) -> List[CaptouchPetalState]:
         """
@@ -86,7 +78,6 @@ class CaptouchState(Protocol):
         """
         ...
 
-
 def read() -> CaptouchState:
     """
     Reads current captouch state from hardware and returns a snapshot in time.
@@ -97,4 +88,4 @@ def calibration_active() -> bool:
     """
     Returns true if the captouch system is current recalibrating.
     """
-    ...
\ No newline at end of file
+    ...
diff --git a/python_payload/mypystubs/hardware.pyi b/python_payload/mypystubs/hardware.pyi
index 14d91ba3539ba4c5b7120be8c52e98d3c973db10..0b39553bd58ac6e7d83fbf080cc4765b7f27b677 100644
--- a/python_payload/mypystubs/hardware.pyi
+++ b/python_payload/mypystubs/hardware.pyi
@@ -2,21 +2,12 @@ import time
 
 from st4m.ui.ctx import Ctx
 
-
 def freertos_sleep(ms: int) -> None: ...
-
 def get_ctx() -> Ctx: ...
-
 def display_pipe_full() -> bool: ...
-
 def display_update(c: Ctx) -> None: ...
-
 def get_captouch(ix: int) -> bool: ...
-
 def left_button_get() -> int: ...
-
 def right_button_get() -> int: ...
-
 def usb_connected() -> bool: ...
-
 def usb_console_active() -> bool: ...
diff --git a/python_payload/mypystubs/time.pyi b/python_payload/mypystubs/time.pyi
index 2a276106b5b96623eaca8a784f2df1184c13e462..2a4d09189575bd5c025026fe3be8e2c2184ea217 100644
--- a/python_payload/mypystubs/time.pyi
+++ b/python_payload/mypystubs/time.pyi
@@ -1 +1,2 @@
-def ticks_ms() -> int: pass
\ No newline at end of file
+def ticks_ms() -> int:
+    pass
diff --git a/python_payload/st4m/__init__.py b/python_payload/st4m/__init__.py
index 033876cbeb5b3f2b0756b1d02df4342ebf8ba835..2aaabd2b504060d133ef481606cb34633af7feff 100644
--- a/python_payload/st4m/__init__.py
+++ b/python_payload/st4m/__init__.py
@@ -3,9 +3,9 @@ from st4m.ui.ctx import Ctx
 from st4m.input import InputState, InputController
 
 __all__ = [
-    'Reactor', 'Responder',
-
-    'InputState', 'InputController',
-
-    'Ctx',
-]
\ No newline at end of file
+    "Reactor",
+    "Responder",
+    "InputState",
+    "InputController",
+    "Ctx",
+]
diff --git a/python_payload/st4m/goose.py b/python_payload/st4m/goose.py
index 77b9ecaa797300e2dac5a5c7268095c5536694af..c4380609ffd25c551305bbf10bafb59f5391869f 100644
--- a/python_payload/st4m/goose.py
+++ b/python_payload/st4m/goose.py
@@ -13,6 +13,7 @@ except:
 if TYPE_CHECKING:
     # We're in MyPy.
     from abc import ABCMeta, abstractmethod
+
     class ABCBase(metaclass=ABCMeta):
         pass
 
@@ -26,6 +27,7 @@ else:
     def abstractmethod(f):
         def _fail():
             raise Exception("abstract method call")
+
         return _fail
 
     try:
@@ -39,11 +41,12 @@ else:
         class Enum:
             pass
 
-__all__ = [
-    'TYPE_CHECKING',
-    'ABCBase', 'abstractmethod',
 
-    'List', 'Optional',
-
-    'Enum',
-]
\ No newline at end of file
+__all__ = [
+    "TYPE_CHECKING",
+    "ABCBase",
+    "abstractmethod",
+    "List",
+    "Optional",
+    "Enum",
+]
diff --git a/python_payload/st4m/input.py b/python_payload/st4m/input.py
index 576bb906cbd084f911d5e46c1361169c05b51262..cdeacc05ba85e4e9efed3729426449ab96af8ecf 100644
--- a/python_payload/st4m/input.py
+++ b/python_payload/st4m/input.py
@@ -8,24 +8,24 @@ class InputState:
     """
     Current state of inputs from badge user. Passed via think() to every
     Responder.
-    
+
     If you want to detect edges, use the stateful InputController.
     """
-    def __init__(self, petal_pressed: List[bool], left_button: int, right_button: int) -> None:
+
+    def __init__(
+        self, petal_pressed: List[bool], left_button: int, right_button: int
+    ) -> None:
         self.petal_pressed = petal_pressed
         self.left_button = left_button
         self.right_button = right_button
-    
+
     @classmethod
-    def gather(cls) -> 'InputState':
+    def gather(cls) -> "InputState":
         """
         Build InputState from current hardware state. Should only be used by the
         Reactor.
         """
-        petal_pressed = [
-            hardware.get_captouch(i)
-            for i in range(10)
-        ]
+        petal_pressed = [hardware.get_captouch(i) for i in range(10)]
         left_button = hardware.left_button_get()
         right_button = hardware.right_button_get()
 
@@ -48,11 +48,11 @@ class Pressable:
     button repeating.
     """
 
-    PRESSED = 'pressed'
-    REPEATED = 'repeated'
-    RELEASED = 'released'
-    DOWN = 'down'
-    UP = 'up'
+    PRESSED = "pressed"
+    REPEATED = "repeated"
+    RELEASED = "released"
+    DOWN = "down"
+    UP = "up"
 
     def __init__(self, state: bool) -> None:
         self._state = state
@@ -93,7 +93,6 @@ class Pressable:
                     self._prev_state = False
                     self._pressed_at = ts
                     self._repeated = True
-        
 
     @property
     def state(self) -> str:
@@ -162,10 +161,10 @@ class Pressable:
         self._ignoring = 2
         self._repeating = False
         self._repeated = False
-    
+
     def __repr__(self) -> str:
-        return '<Pressable: ' + self.state + '>'
-    
+        return "<Pressable: " + self.state + ">"
+
 
 class PetalState(Pressable):
     def __init__(self, ix: int) -> None:
@@ -180,18 +179,16 @@ class CaptouchState:
     The petals are indexed from 0 to 9 (inclusive). Petal 0 is above the USB-C
     socket, then the numbering continues counter-clockwise.
     """
-    __slots__ = ('petals')
+
+    __slots__ = "petals"
 
     def __init__(self) -> None:
-        self.petals = [
-            PetalState(i)
-            for i in range(10)
-        ]
-    
+        self.petals = [PetalState(i) for i in range(10)]
+
     def _update(self, ts: int, hr: InputState) -> None:
         for i, petal in enumerate(self.petals):
             petal._update(ts, hr.petal_pressed[i])
-    
+
     def _ignore_pressed(self) -> None:
         for petal in self.petals:
             petal._ignore_pressed()
@@ -201,15 +198,17 @@ class TriSwitchHandedness(Enum):
     """
     Left or right shoulder button.
     """
-    left = 'left'
-    right = 'right'
+
+    left = "left"
+    right = "right"
 
 
 class TriSwitchState:
     """
     State of a tri-stat shoulder button
     """
-    __slots__ = ('left', 'middle', 'right', 'handedness')
+
+    __slots__ = ("left", "middle", "right", "handedness")
 
     def __init__(self, h: TriSwitchHandedness) -> None:
         self.handedness = h
@@ -219,7 +218,11 @@ class TriSwitchState:
         self.right = Pressable(False)
 
     def _update(self, ts: int, hr: InputState) -> None:
-        st = hr.left_button if self.handedness == TriSwitchHandedness.left else hr.right_button
+        st = (
+            hr.left_button
+            if self.handedness == TriSwitchHandedness.left
+            else hr.right_button
+        )
         self.left._update(ts, st == -1)
         self.middle._update(ts, st == 2)
         self.right._update(ts, st == 1)
@@ -228,7 +231,7 @@ class TriSwitchState:
         self.left._ignore_pressed()
         self.middle._ignore_pressed()
         self.right._ignore_pressed()
-    
+
 
 class InputController:
     """
@@ -241,12 +244,14 @@ class InputController:
 
     Then, access the captouch/left_shoulder/right_shoulder fields.
     """
+
     __slots__ = (
-        'captouch',
-        'left_shoulder',
-        'right_shoulder',
-        '_ts',
+        "captouch",
+        "left_shoulder",
+        "right_shoulder",
+        "_ts",
     )
+
     def __init__(self) -> None:
         self.captouch = CaptouchState()
         self.left_shoulder = TriSwitchState(TriSwitchHandedness.left)
@@ -268,4 +273,3 @@ class InputController:
         self.captouch._ignore_pressed()
         self.left_shoulder._ignore_pressed()
         self.right_shoulder._ignore_pressed()
-
diff --git a/python_payload/st4m/reactor.py b/python_payload/st4m/reactor.py
index 558186f254396ff104bbecca74d9fb5f869f6206..30f1e22436571b98b4c33b9762ed2bdc92b246b3 100644
--- a/python_payload/st4m/reactor.py
+++ b/python_payload/st4m/reactor.py
@@ -4,6 +4,7 @@ from st4m.ui.ctx import Ctx
 
 import time, hardware
 
+
 class Responder(ABCBase):
     """
     Responder is an interface from the Reactor to any running Micropython code
@@ -14,6 +15,7 @@ class Responder(ABCBase):
     The Reactor will call think and draw methods at a somewhat-constant pace in
     order to maintain a smooth system-wide update rate and framerate.
     """
+
     @abstractmethod
     def think(self, ins: InputState, delta_ms: int) -> None:
         """
@@ -37,7 +39,7 @@ class Responder(ABCBase):
         left). Unless specified otherwise by the compositing stack, the screen
         coordinates are +/- 120 in both X and Y (positive numbers towards up and
         right), with 0,0 being the middle of the screen.
-        
+
         The Reactor will then rasterize and blit the result.
 
         The code must not sleep or block during this callback, as that will
@@ -54,7 +56,9 @@ class Reactor:
     It will attempt to run a top Responder with a fixed tickrate a framerate
     that saturates the display rasterization/blitting pipeline.
     """
-    __slots__ = ('_top', '_tickrate_ms', '_last_tick', '_ctx', '_ts')
+
+    __slots__ = ("_top", "_tickrate_ms", "_last_tick", "_ctx", "_ts")
+
     def __init__(self) -> None:
         self._top: Optional[Responder] = None
         self._tickrate_ms: int = 20
@@ -89,14 +93,14 @@ class Reactor:
         if wait > 0:
             hardware.freertos_sleep(wait)
         else:
-            print('too long', wait)
+            print("too long", wait)
 
     def _run_top(self, start: int) -> None:
         # Skip if we have no top Responder.
         if self._top is None:
             return
 
-		# Calculate delta (default to tickrate if running first iteration).
+        # Calculate delta (default to tickrate if running first iteration).
         delta = self._tickrate_ms
         if self._last_tick is not None:
             delta = start - self._last_tick
@@ -106,7 +110,7 @@ class Reactor:
 
         hr = InputState.gather()
 
-		# Think!
+        # Think!
         self._top.think(hr, delta)
 
         # Draw!
@@ -119,4 +123,3 @@ class Reactor:
         if self._ctx is not None and not hardware.display_pipe_full():
             hardware.display_update(self._ctx)
             self._ctx = None
-
diff --git a/python_payload/st4m/ui/ctx.py b/python_payload/st4m/ui/ctx.py
index 7a442cfaec90ed3b51cfc22072e4d15547cf2f8d..ddd00768fcd721e8f92291ca1cb8e9f84e45dc15 100644
--- a/python_payload/st4m/ui/ctx.py
+++ b/python_payload/st4m/ui/ctx.py
@@ -1,5 +1,6 @@
 from st4m.goose import ABCBase, abstractmethod, List
 
+
 class Ctx(ABCBase):
     """
     Ctx is the rendering/rasterization API used by st4m.
@@ -12,34 +13,41 @@ class Ctx(ABCBase):
     in-memory draw list. Then, when the rasterizer is ready, it will rasterize
     said drawlist to pixels in a separate thread.
 
-	A Ctx object is passed to all draw() calls to Responder. This object should
-	only be used within the lifecycle of the draw method and must not be
-	persisted.
+        A Ctx object is passed to all draw() calls to Responder. This object should
+        only be used within the lifecycle of the draw method and must not be
+        persisted.
 
     For more information, see: https://ctx.graphics/
     """
-    __slots__ = ('font_size', 'text_align', 'text_baseline', 'line_width', 'global_alpha')
 
-    CENTER = 'center'
-    MIDDLE = 'middle'
+    __slots__ = (
+        "font_size",
+        "text_align",
+        "text_baseline",
+        "line_width",
+        "global_alpha",
+    )
+
+    CENTER = "center"
+    MIDDLE = "middle"
 
     @abstractmethod
     def __init__(self) -> None:
         self.font_size: float = 10
-        self.text_align: str = 'start'
-        self.text_baseline: str = 'alphabetic'
+        self.text_align: str = "start"
+        self.text_baseline: str = "alphabetic"
         self.line_width: float = 1.0
         self.global_alpha: float = 1.0
 
     @abstractmethod
-    def begin_path(self) -> 'Ctx':
+    def begin_path(self) -> "Ctx":
         """
         Clears the current path if any.
         """
         pass
 
     @abstractmethod
-    def save(self) -> 'Ctx':
+    def save(self) -> "Ctx":
         """
         Stores the transform, clipping state, fill and stroke sources, font
         size, stroking and dashing options.
@@ -47,7 +55,7 @@ class Ctx(ABCBase):
         pass
 
     @abstractmethod
-    def restore(self) -> 'Ctx':
+    def restore(self) -> "Ctx":
         """
         Restores the state previously saved with save, calls to save/restore
         should be balanced.
@@ -55,7 +63,7 @@ class Ctx(ABCBase):
         pass
 
     @abstractmethod
-    def start_frame(self) -> 'Ctx':
+    def start_frame(self) -> "Ctx":
         """
         Prepare for rendering a new frame, clears internal drawlist and
         initializes the state.
@@ -65,7 +73,7 @@ class Ctx(ABCBase):
         pass
 
     @abstractmethod
-    def end_frame(self) -> 'Ctx':
+    def end_frame(self) -> "Ctx":
         """
         We're done rendering a frame, this does nothing on a context created for
         a framebuffer, where drawing commands are immediate.
@@ -75,14 +83,14 @@ class Ctx(ABCBase):
         pass
 
     @abstractmethod
-    def start_group(self) -> 'Ctx':
+    def start_group(self) -> "Ctx":
         """
         Start a compositing group.
         """
         pass
 
     @abstractmethod
-    def end_group(self) -> 'Ctx':
+    def end_group(self) -> "Ctx":
         """
         End a compositing group, the global alpha, compositing mode and blend
         mode set before this call is used to apply the group.
@@ -90,7 +98,7 @@ class Ctx(ABCBase):
         pass
 
     @abstractmethod
-    def clip(self) -> 'Ctx':
+    def clip(self) -> "Ctx":
         """
         Use the current path as a clipping mask, subsequent draw calls are
         limited by the path. The only way to increase the visible area is to
@@ -99,28 +107,39 @@ class Ctx(ABCBase):
         pass
 
     @abstractmethod
-    def rotate(self, x: float) -> 'Ctx':
+    def rotate(self, x: float) -> "Ctx":
         """
         Add rotation to the user to device space transform.
         """
         pass
 
     @abstractmethod
-    def scale(self, x: float, y: float) -> 'Ctx':
+    def scale(self, x: float, y: float) -> "Ctx":
         """
         Scales the user to device transform.
         """
         pass
 
     @abstractmethod
-    def translate(self, x: float, y: float) -> 'Ctx':
+    def translate(self, x: float, y: float) -> "Ctx":
         """
         Adds translation to the user to device transform.
         """
         pass
 
     @abstractmethod
-    def apply_transform(self, a: float, b: float, c: float, d: float, e: float, f: float, g: float, h: float, i: float) -> 'Ctx':
+    def apply_transform(
+        self,
+        a: float,
+        b: float,
+        c: float,
+        d: float,
+        e: float,
+        f: float,
+        g: float,
+        h: float,
+        i: float,
+    ) -> "Ctx":
         """
         Adds a 3x3 matrix on top of the existing user to device space transform.
 
@@ -129,7 +148,7 @@ class Ctx(ABCBase):
         pass
 
     @abstractmethod
-    def line_to(self, x: float, y: float) -> 'Ctx':
+    def line_to(self, x: float, y: float) -> "Ctx":
         """
         Draws a line segment from the position of the last
         {line,move,curve,quad}_to) to the given coordinates.
@@ -137,35 +156,37 @@ class Ctx(ABCBase):
         pass
 
     @abstractmethod
-    def move_to(self, x: float, y: float) -> 'Ctx':
+    def move_to(self, x: float, y: float) -> "Ctx":
         """
         Moves the virtual pen to the given coordinates without drawing anything.
         """
         pass
 
     @abstractmethod
-    def curve_to(self, cx0: float, cy0: float, cx1: float, cy1: float, x: float, y: float) -> 'Ctx':
+    def curve_to(
+        self, cx0: float, cy0: float, cx1: float, cy1: float, x: float, y: float
+    ) -> "Ctx":
         """
         TOD(q3k): document
         """
         pass
 
     @abstractmethod
-    def quad_to(self, cx: float, cy: float, x: float, y: float) -> 'Ctx':
+    def quad_to(self, cx: float, cy: float, x: float, y: float) -> "Ctx":
         """
         TOD(q3k): document
         """
         pass
 
     @abstractmethod
-    def gray(self, a: float) -> 'Ctx':
+    def gray(self, a: float) -> "Ctx":
         """
         Set current draw color to a floating point grayscale value from 0 to 1.
         """
         pass
 
     @abstractmethod
-    def rgb(self, r: float, g: float, b: float) -> 'Ctx':
+    def rgb(self, r: float, g: float, b: float) -> "Ctx":
         """
         Set current draw color to an RGB color defined by component values from
         0 to 1.
@@ -173,7 +194,7 @@ class Ctx(ABCBase):
         pass
 
     @abstractmethod
-    def rgba(self, r: float, g: float, b: float, a: float) -> 'Ctx': 
+    def rgba(self, r: float, g: float, b: float, a: float) -> "Ctx":
         """
         Set current draw color to an RGBA color defined by component values from
         0 to 1.
@@ -181,105 +202,121 @@ class Ctx(ABCBase):
         pass
 
     @abstractmethod
-    def arc_to(self, x1: float, y1: float, x2: float, y2: float, radius: float) -> 'Ctx':
+    def arc_to(
+        self, x1: float, y1: float, x2: float, y2: float, radius: float
+    ) -> "Ctx":
         """
         TOD(q3k): document
         """
         pass
 
     @abstractmethod
-    def rel_line_to(self, x: float, y: float) -> 'Ctx':
+    def rel_line_to(self, x: float, y: float) -> "Ctx":
         """
         TOD(q3k): document
         """
         pass
 
     @abstractmethod
-    def rel_move_to(self, x: float, y: float) -> 'Ctx':
+    def rel_move_to(self, x: float, y: float) -> "Ctx":
         """
         TOD(q3k): document
         """
         pass
 
     @abstractmethod
-    def rel_curve_to(self, cx0: float, cy0: float, cx1: float, cy1: float, x: float, y: float) -> 'Ctx':
+    def rel_curve_to(
+        self, cx0: float, cy0: float, cx1: float, cy1: float, x: float, y: float
+    ) -> "Ctx":
         """
         TOD(q3k): document
         """
         pass
 
     @abstractmethod
-    def rel_quad_to(self, cx: float, cy: float, x: float, y: float) -> 'Ctx':
+    def rel_quad_to(self, cx: float, cy: float, x: float, y: float) -> "Ctx":
         """
         TOD(q3k): document
         """
         pass
 
     @abstractmethod
-    def rel_arc_to(self, x1: float, y1: float, x2: float, y2: float, radius: float) -> 'Ctx':
+    def rel_arc_to(
+        self, x1: float, y1: float, x2: float, y2: float, radius: float
+    ) -> "Ctx":
         """
         TOD(q3k): document
         """
         pass
 
     @abstractmethod
-    def rectangle(self, x: float, y: float, w: float, h: float) -> 'Ctx':
+    def rectangle(self, x: float, y: float, w: float, h: float) -> "Ctx":
         """
         TOD(q3k): document
         """
         pass
 
     @abstractmethod
-    def round_rectangle(self, x: float, y: float, w: float, h: float, r: float) -> 'Ctx':
+    def round_rectangle(
+        self, x: float, y: float, w: float, h: float, r: float
+    ) -> "Ctx":
         """
         TOD(q3k): document
         """
         pass
 
     @abstractmethod
-    def arc(self, x: float, y: float, radius: float, angle1: float, angle2: float, direction: float) -> 'Ctx':
+    def arc(
+        self,
+        x: float,
+        y: float,
+        radius: float,
+        angle1: float,
+        angle2: float,
+        direction: float,
+    ) -> "Ctx":
         """
         TOD(q3k): document
         """
         pass
 
     @abstractmethod
-    def close_path(self) -> 'Ctx':
+    def close_path(self) -> "Ctx":
         """
         TOD(q3k): document
         """
         pass
 
     @abstractmethod
-    def preserve(self) -> 'Ctx':
+    def preserve(self) -> "Ctx":
         """
         TOD(q3k): document
         """
         pass
 
     @abstractmethod
-    def fill(self) -> 'Ctx':
+    def fill(self) -> "Ctx":
         """
         TOD(q3k): document
         """
         pass
 
     @abstractmethod
-    def stroke(self) -> 'Ctx':
+    def stroke(self) -> "Ctx":
         """
         TOD(q3k): document
         """
         pass
 
     @abstractmethod
-    def paint(self) -> 'Ctx':
+    def paint(self) -> "Ctx":
         """
         TOD(q3k): document
         """
         pass
 
     @abstractmethod
-    def linear_gradient(self, x0: float, y0: float, x1: float, y1: float) -> 'Ctx':
+    def linear_gradient(self, x0: float, y0: float, x1: float, y1: float) -> "Ctx":
         """
         Change the source to a linear gradient from x0,y0 to x1,y1, by default
         an empty gradient from black to white exists, add stops with
@@ -290,7 +327,9 @@ class Ctx(ABCBase):
         pass
 
     @abstractmethod
-    def radial_gradient(self, x0: float, y0: float, r0: float, x1: float, y1: float, r1: float) -> 'Ctx':
+    def radial_gradient(
+        self, x0: float, y0: float, r0: float, x1: float, y1: float, r1: float
+    ) -> "Ctx":
         """
         Change the source to a radial gradient from a circle x0,y0 with radius0
         to an outer circle x1,y1 with radidus r1.
@@ -301,15 +340,15 @@ class Ctx(ABCBase):
         pass
 
     @abstractmethod
-    def logo(self, x: float, y: float, dim: float) -> 'Ctx':
+    def logo(self, x: float, y: float, dim: float) -> "Ctx":
         """
         TOD(q3k): document
         """
         pass
 
     @abstractmethod
-    def text(self, text: str) -> 'Ctx':
+    def text(self, text: str) -> "Ctx":
         """
         TOD(q3k): document
         """
-        pass
\ No newline at end of file
+        pass
diff --git a/python_payload/st4m/ui/interactions.py b/python_payload/st4m/ui/interactions.py
index a665d17df56f38db5030b8067ca686b0e4c769cb..f8eb2f17a863eb437813ab224a25afb25cc47aab 100644
--- a/python_payload/st4m/ui/interactions.py
+++ b/python_payload/st4m/ui/interactions.py
@@ -23,11 +23,12 @@ class ScrollController(st4m.Responder):
     effects like acceleration and past-end-of-list bounce-back. This value
     should be used to render the current state of the scrolling list.
     """
+
     __slots__ = (
-        '_nitems',
-        '_target_position',
-        '_current_position',
-        '_velocity',
+        "_nitems",
+        "_target_position",
+        "_current_position",
+        "_velocity",
     )
 
     def __init__(self) -> None:
@@ -35,7 +36,7 @@ class ScrollController(st4m.Responder):
         self._target_position = 0
         self._current_position = 0.0
         self._velocity: float = 0.0
-    
+
     def set_item_count(self, count: int) -> None:
         """
         Set how many items this scrollable list contains. Currently, updating
@@ -108,7 +109,7 @@ class ScrollController(st4m.Responder):
         Returns true if the scrollable list is at its leftmost (0) position.
         """
         return self._target_position <= 0
-    
+
     def at_right_limit(self) -> bool:
         """
         Returns true if the scrollable list is as its rightmost (Nitems-1)
@@ -147,5 +148,3 @@ class ScrollController(st4m.Responder):
     def _physics_integrate(self, delta: float) -> None:
         self._velocity -= self._velocity * delta * 10
         self._current_position += self._velocity * delta
-
-
diff --git a/python_payload/st4m/ui/menu.py b/python_payload/st4m/ui/menu.py
index a2d85b4fbe58c9a9b41eced349d5ac227fd0ecad..e076dedd52dce11e28f6bb4ca76de0c89384d636 100644
--- a/python_payload/st4m/ui/menu.py
+++ b/python_payload/st4m/ui/menu.py
@@ -3,7 +3,13 @@ import st4m
 from st4m import Responder
 from st4m.goose import ABCBase, abstractmethod, List, Optional
 from st4m.input import InputState, InputController
-from st4m.ui.view import ViewWithInputState, View, ViewManager, ViewTransitionSwipeLeft, ViewTransitionSwipeRight
+from st4m.ui.view import (
+    ViewWithInputState,
+    View,
+    ViewManager,
+    ViewTransitionSwipeLeft,
+    ViewTransitionSwipeRight,
+)
 from st4m.ui.interactions import ScrollController
 from st4m.ui.ctx import Ctx
 
@@ -12,7 +18,7 @@ class MenuItem(ABCBase):
     """
     An abstract MenuItem to be implemented by concrete impementations.
 
-    A MenuItem implementation can be added to a MenuController 
+    A MenuItem implementation can be added to a MenuController
     """
 
     @abstractmethod
@@ -37,6 +43,7 @@ class MenuItemForeground(MenuItem):
     """
     A MenuItem which, when activated, navigates to the given View.
     """
+
     def __init__(self, label: str, r: View) -> None:
         self._r = r
         self._label = label
@@ -53,6 +60,7 @@ class MenuItemNoop(MenuItem):
     """
     A MenuItem which does nothing.
     """
+
     def __init__(self, label: str) -> None:
         self._label = label
 
@@ -67,6 +75,7 @@ class MenuItemBack(MenuItem):
     """
     A MenuItem which, when activatd, navigates back in history.
     """
+
     def press(self, vm: Optional[ViewManager]) -> None:
         if vm is not None:
             vm.pop(ViewTransitionSwipeRight())
@@ -83,10 +92,11 @@ class MenuController(ViewWithInputState):
     Implementers must implement draw() and use self._items and
     self._scroll_controller to display menu items accordingly.
     """
+
     __slots__ = (
-        '_items',
-        '_scroll_controller',
-        '_view_manager',
+        "_items",
+        "_scroll_controller",
+        "_view_manager",
     )
 
     def __init__(self, items: List[MenuItem], vm: Optional[ViewManager]) -> None:
@@ -100,7 +110,7 @@ class MenuController(ViewWithInputState):
     def _parse_state(self) -> None:
         left = self.input.left_shoulder.left
         right = self.input.left_shoulder.right
-        
+
         if left.pressed:
             self._scroll_controller.scroll_left()
             return
@@ -135,4 +145,3 @@ class MenuController(ViewWithInputState):
         Automatically called on canonical user input.
         """
         self._items[self._scroll_controller.target_position()].press(self._view_manager)
-
diff --git a/python_payload/st4m/ui/view.py b/python_payload/st4m/ui/view.py
index a66d9194f357d2854ae3333791ac216e2477dbfe..da1948874465ab3cded8816ebe7f9582b0cd50d6 100644
--- a/python_payload/st4m/ui/view.py
+++ b/python_payload/st4m/ui/view.py
@@ -30,9 +30,8 @@ class ViewWithInputState(View):
 
     Remember to call super().think() in think()!
     """
-    __slots__ = (
-        'input',
-    )
+
+    __slots__ = ("input",)
 
     def __init__(self) -> None:
         self.input = InputController()
@@ -50,8 +49,11 @@ class ViewTransition(ABCBase):
 
     Can be implemented by the user to provide transition animations.
     """
+
     @abstractmethod
-    def draw(self, ctx: Ctx, transition: float, incoming: Responder, outgoing: Responder) -> None:
+    def draw(
+        self, ctx: Ctx, transition: float, incoming: Responder, outgoing: Responder
+    ) -> None:
         """
         Called when the ViewManager performs a transition from the outgoing
         responder to the incoming responder. The implementer should draw both
@@ -67,7 +69,10 @@ class ViewTransitionBlend(ViewTransition):
     """
     Transition from one view to another by opacity blending.
     """
-    def draw(self, ctx: Ctx, transition: float, incoming: Responder, outgoing: Responder) -> None:
+
+    def draw(
+        self, ctx: Ctx, transition: float, incoming: Responder, outgoing: Responder
+    ) -> None:
         ctx.start_group()
         outgoing.draw(ctx)
         ctx.end_group()
@@ -82,7 +87,10 @@ class ViewTransitionSwipeLeft(ViewTransition):
     """
     Swipe the outoing view to the left and replace it with the incoming view.
     """
-    def draw(self, ctx: Ctx, transition: float, incoming: Responder, outgoing: Responder) -> None:
+
+    def draw(
+        self, ctx: Ctx, transition: float, incoming: Responder, outgoing: Responder
+    ) -> None:
         ctx.save()
         ctx.translate(transition * -240, 0)
         outgoing.draw(ctx)
@@ -98,7 +106,10 @@ class ViewTransitionSwipeRight(ViewTransition):
     """
     Swipe the outoing view to the right and replace it with the incoming view.
     """
-    def draw(self, ctx: Ctx, transition: float, incoming: Responder, outgoing: Responder) -> None:
+
+    def draw(
+        self, ctx: Ctx, transition: float, incoming: Responder, outgoing: Responder
+    ) -> None:
         ctx.save()
         ctx.translate(transition * 240, 0)
         outgoing.draw(ctx)
@@ -117,6 +128,7 @@ class ViewManager(Responder):
     It manages a history of Views, to which new Views can be pushed and then
     popped.
     """
+
     def __init__(self, vt: ViewTransition) -> None:
         """
         Create a new ViewManager with a default ViewTransition.
@@ -124,7 +136,7 @@ class ViewManager(Responder):
         self._incoming: Optional[View] = None
         self._outgoing: Optional[View] = None
 
-		# Transition time.
+        # Transition time.
         self._time_ms = 150
 
         self._default_vt = vt
@@ -140,9 +152,9 @@ class ViewManager(Responder):
             if self._transition >= 1.0:
                 self._transition = 0
                 self._transitioning = False
-                
+
                 self._outgoing = None
-        
+
         if self._outgoing is not None:
             self._outgoing.think(ins, delta_ms)
         if self._incoming is not None:
@@ -195,4 +207,4 @@ class ViewManager(Responder):
         animation.
         """
         r = self._history.pop()
-        self.replace(r, override_vt)
\ No newline at end of file
+        self.replace(r, override_vt)
diff --git a/sim/fakes/captouch.py b/sim/fakes/captouch.py
index 4706637827149178f303530a0547daddb8cf69ed..a7c4f3d46366968ad22ebc45edaccf87905e172a 100644
--- a/sim/fakes/captouch.py
+++ b/sim/fakes/captouch.py
@@ -11,10 +11,10 @@ class CaptouchPetalPadsState:
     @property
     def tip(self) -> bool:
         return self._tip
-    
+
     @property
     def base(self) -> bool:
-        return  self._base
+        return self._base
 
     @property
     def cw(self) -> bool:
@@ -61,6 +61,7 @@ class CaptouchState:
 
 def read() -> CaptouchState:
     import hardware
+
     hardware._sim.process_events()
     hardware._sim.render_gui_lazy()
     petals = hardware._sim.petals
@@ -83,4 +84,4 @@ def read() -> CaptouchState:
 
 
 def calibration_active() -> bool:
-    return False
\ No newline at end of file
+    return False
diff --git a/sim/fakes/ctx.py b/sim/fakes/ctx.py
index 72a91d2ac23cab13819e84a318fe65138faed1a9..bade7298b5290b82bfe469d6339f6faa23d395fa 100644
--- a/sim/fakes/ctx.py
+++ b/sim/fakes/ctx.py
@@ -16,13 +16,14 @@ class Wasm:
     Wasm wraps access to WebAssembly functions, converting to/from Python types
     as needed. It's intended to be used as a singleton.
     """
+
     def __init__(self):
         store = wasmer.Store(wasmer.engine.JIT(wasmer_compiler_cranelift.Compiler))
         simpath = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
-        wasmpath = os.path.join(simpath, 'wasm', 'ctx.wasm')
-        module = wasmer.Module(store, open(wasmpath, 'rb').read())
+        wasmpath = os.path.join(simpath, "wasm", "ctx.wasm")
+        module = wasmer.Module(store, open(wasmpath, "rb").read())
         wasi_version = wasmer.wasi.get_version(module, strict=False)
-        wasi_env = wasmer.wasi.StateBuilder('badge23sim').finalize()
+        wasi_env = wasmer.wasi.StateBuilder("badge23sim").finalize()
         import_object = wasi_env.generate_import_object(store, wasi_version)
         instance = wasmer.Instance(module, import_object)
         self._i = instance
@@ -34,12 +35,12 @@ class Wasm:
         self._i.exports.free(p)
 
     def ctx_parse(self, ctx, s):
-        s = s.encode('utf-8')
+        s = s.encode("utf-8")
         slen = len(s) + 1
         p = self.malloc(slen)
         mem = self._i.exports.memory.uint8_view(p)
-        mem[0:slen-1] = s
-        mem[slen-1] = 0
+        mem[0 : slen - 1] = s
+        mem[slen - 1] = 0
         self._i.exports.ctx_parse(ctx, p)
         self.free(p)
 
@@ -55,7 +56,9 @@ class Wasm:
         # framebuffer into pygame's surfaces, which is a _huge_ speed benefit
         # (difference between ~10FPS and 500+FPS!).
         BRGA8 = 5
-        return fb, self._i.exports.ctx_new_for_framebuffer(fb, width, height, width * 4, BRGA8)
+        return fb, self._i.exports.ctx_new_for_framebuffer(
+            fb, width, height, width * 4, BRGA8
+        )
 
     def ctx_new_drawlist(self, width, height):
         return self._i.exports.ctx_new_drawlist(width, height)
@@ -65,12 +68,12 @@ class Wasm:
         return self._i.exports.ctx_apply_transform(ctx, *args)
 
     def ctx_text_width(self, ctx, text):
-        s = text.encode('utf-8')
+        s = text.encode("utf-8")
         slen = len(s) + 1
         p = self.malloc(slen)
         mem = self._i.exports.memory.uint8_view(p)
-        mem[0:slen-1] = s
-        mem[slen-1] = 0
+        mem[0 : slen - 1] = s
+        mem[slen - 1] = 0
         res = self._i.exports.ctx_text_width(ctx, p)
         self.free(p)
         return res
@@ -81,8 +84,10 @@ class Wasm:
     def ctx_render_ctx(self, ctx, dctx):
         return self._i.exports.ctx_render_ctx(ctx, dctx)
 
+
 _wasm = Wasm()
 
+
 class Ctx:
     """
     Ctx implements a subset of uctx [1]. It should be extended as needed as we
@@ -90,12 +95,13 @@ class Ctx:
 
     [1] - https://ctx.graphics/uctx/
     """
-    LEFT = 'left'
-    RIGHT = 'right'
-    CENTER = 'center'
-    END = 'end'
-    MIDDLE = 'middle'
-    BEVEL = 'bevel'
+
+    LEFT = "left"
+    RIGHT = "right"
+    CENTER = "center"
+    END = "end"
+    MIDDLE = "middle"
+    BEVEL = "bevel"
 
     def __init__(self, _ctx):
         self._ctx = _ctx
@@ -107,7 +113,7 @@ class Ctx:
     @text_align.setter
     def text_align(self, v):
         self._emit(f"textAlign {v}")
-    
+
     @property
     def text_baseline(self):
         return None
@@ -127,7 +133,7 @@ class Ctx:
     @property
     def font_size(self):
         return None
-    
+
     @font_size.setter
     def font_size(self, v):
         self._emit(f"fontSize {v:.3f}")
@@ -135,7 +141,7 @@ class Ctx:
     @property
     def global_alpha(self):
         return None
-    
+
     @global_alpha.setter
     def global_alpha(self, v):
         self._emit(f"globalAlpha {v:.3f}")
@@ -167,7 +173,6 @@ class Ctx:
         self._emit(f"gray {v:.3f}")
         return self
 
-
     def rgba(self, r, g, b, a):
         # TODO(q3k): dispatch by type instead of value, warn on
         # ambiguous/unexpected values for type.
@@ -190,11 +195,13 @@ class Ctx:
         return self
 
     def text(self, s):
-        self._emit(f"text \"{s}\"")
+        self._emit(f'text "{s}"')
         return self
 
     def round_rectangle(self, x, y, width, height, radius):
-        self._emit(f"roundRectangle {int(x)} {int(y)} {int(width)} {int(height)} {radius}")
+        self._emit(
+            f"roundRectangle {int(x)} {int(y)} {int(width)} {int(height)} {radius}"
+        )
         return self
 
     def rectangle(self, x, y, width, height):
@@ -225,8 +232,10 @@ class Ctx:
         self._emit(f"fill")
         return self
 
-    def arc(self, x, y , radius, arc_from, arc_to, direction):
-        self._emit(f"arc {int(x)} {int(y)} {int(radius)} {arc_from:.4f} {arc_to:.4f} {1 if direction else 0}")
+    def arc(self, x, y, radius, arc_from, arc_to, direction):
+        self._emit(
+            f"arc {int(x)} {int(y)} {int(radius)} {arc_from:.4f} {arc_to:.4f} {1 if direction else 0}"
+        )
         return self
 
     def text_width(self, text):
diff --git a/sim/fakes/hardware.py b/sim/fakes/hardware.py
index 3f6ef563b41b8dc2c00ad2cfd565b5b4e60a0493..4afe93921058c0facc39d19027ae112637f58780 100644
--- a/sim/fakes/hardware.py
+++ b/sim/fakes/hardware.py
@@ -11,7 +11,7 @@ screen_w = 814
 screen_h = 854
 screen = pygame.display.set_mode(size=(screen_w, screen_h))
 simpath = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
-bgpath = os.path.join(simpath, 'background.png')
+bgpath = os.path.join(simpath, "background.png")
 background = pygame.image.load(bgpath)
 
 
@@ -20,15 +20,16 @@ class Input:
     Input implements an input overlay (for petals or buttons) that can be
     mouse-picked by the user, and in the future also keyboard-controlled.
     """
+
     # Pixels positions of each marker.
     POSITIONS = []
     # Pixel size (diameter) of each marker.
     MARKER_SIZE = 100
 
     # Colors for various states (RGBA).
-    COLOR_HELD = (0x5b, 0x5b, 0x5b, 0xa0)
-    COLOR_HOVER = (0x6b, 0x6b, 0x6b, 0xa0)
-    COLOR_IDLE = (0x8b, 0x8b, 0x8b, 0x80)
+    COLOR_HELD = (0x5B, 0x5B, 0x5B, 0xA0)
+    COLOR_HOVER = (0x6B, 0x6B, 0x6B, 0xA0)
+    COLOR_IDLE = (0x8B, 0x8B, 0x8B, 0x80)
 
     def __init__(self):
         self._state = [False for _ in self.POSITIONS]
@@ -71,40 +72,74 @@ class Input:
         s = self.state()
         for i, (x, y) in enumerate(self.POSITIONS):
             if s[i]:
-                pygame.draw.circle(surface, self.COLOR_HELD, (x, y), self.MARKER_SIZE//2)
+                pygame.draw.circle(
+                    surface, self.COLOR_HELD, (x, y), self.MARKER_SIZE // 2
+                )
             elif i == self._mouse_hover:
-                pygame.draw.circle(surface, self.COLOR_HOVER, (x, y), self.MARKER_SIZE//2)
+                pygame.draw.circle(
+                    surface, self.COLOR_HOVER, (x, y), self.MARKER_SIZE // 2
+                )
             else:
-                pygame.draw.circle(surface, self.COLOR_IDLE, (x, y), self.MARKER_SIZE//2)
+                pygame.draw.circle(
+                    surface, self.COLOR_IDLE, (x, y), self.MARKER_SIZE // 2
+                )
 
 
 class PetalsInput(Input):
     _petal_positions_top = [
-        (406, 172), (164, 352), (254, 637), (554, 637), (652, 348),
+        (406, 172),
+        (164, 352),
+        (254, 637),
+        (554, 637),
+        (652, 348),
     ]
     _petal_positions_bottom = [
-        (213, 162), (99, 527), (402, 746), (710, 527), (597, 167)
+        (213, 162),
+        (99, 527),
+        (402, 746),
+        (710, 527),
+        (597, 167),
     ]
-    POSITIONS = list(itertools.chain(*[
-        [
-            (x + math.cos(i * -1.256 + 1.57) * 40, y + math.sin(i * -1.256 + 1.57) * 40), # base
-            (x + math.cos(i * -1.256 + 5.75) * 40, y + math.sin(i * -1.256 + 5.75) * 40), # cw
-            (x + math.cos(i * -1.256 + 3.66) * 40, y + math.sin(i * -1.256 + 3.66) * 40), # ccw
-        ]
-        for i, (x, y) in enumerate(_petal_positions_top)
-    ] + [
-        [
-            (x + math.cos(i * -1.256 - 2.20) * 40, y + math.sin(i * -1.256 - 2.20) * 40), # tip
-            (x + math.cos(i * -1.256 - 5.34) * 40, y + math.sin(i * -1.256 - 5.34) * 40), # base
-        ]
-        for i, (x, y) in enumerate(_petal_positions_bottom)
-    ]))
+    POSITIONS = list(
+        itertools.chain(
+            *[
+                [
+                    (
+                        x + math.cos(i * -1.256 + 1.57) * 40,
+                        y + math.sin(i * -1.256 + 1.57) * 40,
+                    ),  # base
+                    (
+                        x + math.cos(i * -1.256 + 5.75) * 40,
+                        y + math.sin(i * -1.256 + 5.75) * 40,
+                    ),  # cw
+                    (
+                        x + math.cos(i * -1.256 + 3.66) * 40,
+                        y + math.sin(i * -1.256 + 3.66) * 40,
+                    ),  # ccw
+                ]
+                for i, (x, y) in enumerate(_petal_positions_top)
+            ]
+            + [
+                [
+                    (
+                        x + math.cos(i * -1.256 - 2.20) * 40,
+                        y + math.sin(i * -1.256 - 2.20) * 40,
+                    ),  # tip
+                    (
+                        x + math.cos(i * -1.256 - 5.34) * 40,
+                        y + math.sin(i * -1.256 - 5.34) * 40,
+                    ),  # base
+                ]
+                for i, (x, y) in enumerate(_petal_positions_bottom)
+            ]
+        )
+    )
     MARKER_SIZE = 40
 
     def _index_for_petal_pad(self, petal, pad):
         if petal >= 10:
             raise ValueError("petal cannot be > 10")
-        
+
         # convert from st3m/bsp index into input state index
         top = False
         if petal % 2 == 0:
@@ -117,18 +152,18 @@ class PetalsInput(Input):
             res += 3 * 5
 
         if top:
-            if pad == 1: # ccw
+            if pad == 1:  # ccw
                 res += 2
-            elif pad == 2: # cw
+            elif pad == 2:  # cw
                 res += 1
-            elif pad == 3: # base
+            elif pad == 3:  # base
                 res += 0
             else:
                 raise ValueError("invalid pad number")
         else:
-            if pad == 0: # tip
+            if pad == 0:  # tip
                 res += 0
-            elif pad == 3: # base
+            elif pad == 3:  # base
                 res += 1
             else:
                 raise ValueError("invalid pad number")
@@ -154,13 +189,17 @@ class PetalsInput(Input):
 
 class ButtonsInput(Input):
     POSITIONS = [
-        ( 24, 240), ( 56, 240), ( 88, 240),
-        (724, 240), (756, 240), (788, 240),
+        (24, 240),
+        (56, 240),
+        (88, 240),
+        (724, 240),
+        (756, 240),
+        (788, 240),
     ]
     MARKER_SIZE = 20
-    COLOR_HELD = (0x80, 0x80, 0x80, 0xff)
-    COLOR_HOVER = (0x40, 0x40, 0x40, 0xff)
-    COLOR_IDLE = (0x20, 0x20, 0x20, 0xff)
+    COLOR_HELD = (0x80, 0x80, 0x80, 0xFF)
+    COLOR_HOVER = (0x40, 0x40, 0x40, 0xFF)
+    COLOR_IDLE = (0x20, 0x20, 0x20, 0xFF)
 
 
 class Simulation:
@@ -172,11 +211,46 @@ class Simulation:
     # Pixel coordinates of each LED. The order is the same as the hardware
     # WS2812 chain, not the order as expected by the micropython API!
     LED_POSITIONS = [
-        (660, 455), (608, 490), (631, 554), (648, 618), (659, 690), (655, 770), (571, 746), (502, 711),
-        (452, 677), (401, 639), (352, 680), (299, 713), (241, 745), (151, 771), (147, 682), (160, 607),
-        (176, 549), (197, 491), (147, 453), ( 98, 416), ( 43, 360), (  0, 292), ( 64, 267), (144, 252),
-        (210, 248), (276, 249), (295, 190), (318, 129), (351,  65), (404,   0), (456,  64), (490, 131),
-        (511, 186), (529, 250), (595, 247), (663, 250), (738, 264), (810, 292), (755, 371), (705, 419),
+        (660, 455),
+        (608, 490),
+        (631, 554),
+        (648, 618),
+        (659, 690),
+        (655, 770),
+        (571, 746),
+        (502, 711),
+        (452, 677),
+        (401, 639),
+        (352, 680),
+        (299, 713),
+        (241, 745),
+        (151, 771),
+        (147, 682),
+        (160, 607),
+        (176, 549),
+        (197, 491),
+        (147, 453),
+        (98, 416),
+        (43, 360),
+        (0, 292),
+        (64, 267),
+        (144, 252),
+        (210, 248),
+        (276, 249),
+        (295, 190),
+        (318, 129),
+        (351, 65),
+        (404, 0),
+        (456, 64),
+        (490, 131),
+        (511, 186),
+        (529, 250),
+        (595, 247),
+        (663, 250),
+        (738, 264),
+        (810, 292),
+        (755, 371),
+        (705, 419),
     ]
 
     def __init__(self):
@@ -196,7 +270,9 @@ class Simulation:
         # corresponding surface when there was no change to its render data.
         self._led_surface = pygame.Surface((screen_w, screen_h), flags=pygame.SRCALPHA)
         self._led_surface_dirty = True
-        self._petal_surface = pygame.Surface((screen_w, screen_h), flags=pygame.SRCALPHA)
+        self._petal_surface = pygame.Surface(
+            (screen_w, screen_h), flags=pygame.SRCALPHA
+        )
         self._petal_surface_dirty = True
         self._full_surface = pygame.Surface((screen_w, screen_h), flags=pygame.SRCALPHA)
         self._oled_surface = pygame.Surface((240, 240), flags=pygame.SRCALPHA)
@@ -215,19 +291,13 @@ class Simulation:
         # that is True if the pixel corresponding to this mask's bit is part of
         # the OLED disc, and false otherwise.
         mask = [
-            [
-                math.sqrt((x - 120)**2 + (y - 120)**2) <= 120
-                for x in range(240)
-            ]
+            [math.sqrt((x - 120) ** 2 + (y - 120) ** 2) <= 120 for x in range(240)]
             for y in range(240)
         ]
         # Now, we iterate the mask row-by-row and find the first True bit in
         # it. The offset within that row is our per-row offset for the
         # rendering routine.
-        self._oled_offset = [
-            m.index(True)
-            for m in mask
-        ]
+        self._oled_offset = [m.index(True) for m in mask]
 
     def process_events(self):
         """
@@ -262,14 +332,14 @@ class Simulation:
         surface.fill((0, 0, 0, 0))
         buf = surface.get_buffer()
 
-        fb = fb[:240*240*4]
+        fb = fb[: 240 * 240 * 4]
         for y in range(240):
             # Use precalculated row offset to turn OLED disc into square
             # bounded plane.
             offset = self._oled_offset[y]
             start_offs_bytes = y * 240 * 4
             start_offs_bytes += offset * 4
-            end_offs_bytes = (y+1) * 240 * 4
+            end_offs_bytes = (y + 1) * 240 * 4
             end_offs_bytes -= offset * 4
             buf.write(bytes(fb[start_offs_bytes:end_offs_bytes]), start_offs_bytes)
 
@@ -309,7 +379,7 @@ class Simulation:
         off_y = center_y - (240 // 2)
         full.blit(self._oled_surface, (off_x, off_y))
 
-        screen.blit(full, (0,0))
+        screen.blit(full, (0, 0))
         pygame.display.flip()
 
     def render_gui_lazy(self):
@@ -319,7 +389,7 @@ class Simulation:
         this call.
         """
         target_fps = 60.0
-        d = 1/target_fps
+        d = 1 / target_fps
 
         if self.last_gui_render is None:
             self.render_gui_now()
@@ -362,6 +432,7 @@ def captouch_calibration_active():
 
 import ctx
 
+
 class FramebufferManager:
     def __init__(self):
         self._free = []
@@ -369,7 +440,7 @@ class FramebufferManager:
             fb, c = ctx._wasm.ctx_new_for_framebuffer(240, 240)
             ctx._wasm.ctx_apply_transform(c, 1, 0, 120, 0, 1, 120, 0, 0, 1)
             self._free.append((fb, c))
-    
+
     def get(self):
         if len(self._free) == 0:
             return None, None
@@ -381,8 +452,10 @@ class FramebufferManager:
     def put(self, fb, ctx):
         self._free.append((fb, ctx))
 
+
 fbm = FramebufferManager()
 
+
 def get_ctx():
     dctx = ctx._wasm.ctx_new_drawlist(240, 240)
     return ctx.Ctx(dctx)
@@ -435,22 +508,28 @@ def get_button_state(left):
 
 menu_button_left = 0
 
+
 def menu_button_get():
     return get_button_state(menu_button_left)
 
+
 def application_button_get():
     return get_button_state(1 - menu_button_left)
 
+
 def left_button_get():
     return get_button_state(1)
 
+
 def right_button_get():
     return get_button_state(0)
 
+
 def menu_button_set_left(_broken):
     global menu_button_left
     menu_button_left = 1
 
+
 def menu_button_get_left():
     return menu_button_left
 
@@ -460,18 +539,23 @@ def get_captouch(a):
     _sim.render_gui_lazy()
     return _sim.petals.state_for_petal(a)
 
-#TODO(iggy/q3k do proper positional captouch)
+
+# TODO(iggy/q3k do proper positional captouch)
 def captouch_get_petal_rad(a):
     return 0
 
+
 def captouch_get_petal_phi(a):
     return 0
 
+
 def captouch_get_petal_pad(i, x):
     return 0
 
+
 def freertos_sleep(ms):
     import _time
+
     _time.sleep(ms / 1000.0)
 
 
@@ -482,18 +566,21 @@ def scope_draw(ctx):
     ctx.move_to(x, 0)
     for i in range(240):
         x2 = x + i
-        y2 = math.sin(i/10) * 80
+        y2 = math.sin(i / 10) * 80
         ctx.line_to(x2, y2)
     ctx.line_to(130, 0)
     ctx.line_to(130, 130)
     ctx.line_to(-130, 130)
     ctx.line_to(-130, 0)
 
+
 def usb_connected():
     return True
 
+
 def usb_console_active():
     return True
 
+
 def i2c_scan():
     return [16, 44, 45, 85, 109, 110]
diff --git a/sim/fakes/kernel.py b/sim/fakes/kernel.py
index 62893ff8dfeadad3f7bbacb0670143303997d69a..25fe328f2ac239c9d0bfc6a54ebc17dad6f6c5ce 100644
--- a/sim/fakes/kernel.py
+++ b/sim/fakes/kernel.py
@@ -5,9 +5,11 @@ class FakeHeapKindStats:
         self.total_allocated_bytes = 1337
         self.largest_free_block = 1337
 
+
 class FakeHeapStats:
-    general = FakeHeapKindStats('general')
-    dma = FakeHeapKindStats('dma')
+    general = FakeHeapKindStats("general")
+    dma = FakeHeapKindStats("dma")
+
 
 def heap_stats():
     return FakeHeapStats()
diff --git a/sim/fakes/leds.py b/sim/fakes/leds.py
index c40b76681dc77f8702ef7e0e55f6a355851b84da..3656f5334b03254eb8e9b989794370d0282572d1 100644
--- a/sim/fakes/leds.py
+++ b/sim/fakes/leds.py
@@ -4,7 +4,7 @@ import pygame
 
 
 def set_rgb(ix, r, g, b):
-    ix = ((39-ix) - 2 + 32)%40;
+    ix = ((39 - ix) - 2 + 32) % 40
 
     r = r << 3
     g = g << 2
@@ -17,6 +17,7 @@ def set_rgb(ix, r, g, b):
         b = 255
     _sim.set_led_rgb(ix, r, g, b)
 
+
 def set_all_rgb(r, g, b):
     for i in range(40):
         set_rgb(i, r, g, b)
diff --git a/sim/fakes/time.py b/sim/fakes/time.py
index a710a2fcf62c00a8fc26617bf25c700578c98847..e87af66b1f8f9340ac2ed5cb8b72aa58ca01cabe 100644
--- a/sim/fakes/time.py
+++ b/sim/fakes/time.py
@@ -1,14 +1,19 @@
 import importlib
-_time = importlib.import_module('_time')
+
+_time = importlib.import_module("_time")
+
 
 def sleep_ms(ms):
     _time.sleep(ms * 0.001)
 
+
 def ticks_ms():
     return int(_time.time() * 1000)
 
+
 def ticks_diff(a, b):
     return a - b
 
+
 def ticks_add(a, b):
     return a + b
diff --git a/sim/run.py b/sim/run.py
index 31fb796fe76d10d22afba44253246436db0aeae1..b031d107f0594b542c83df0304ed60be13c71f05 100644
--- a/sim/run.py
+++ b/sim/run.py
@@ -24,22 +24,22 @@ class UnderscoreFinder(importlib.abc.MetaPathFinder):
         self.pathfinder = pathfinder
 
     def find_spec(self, fullname, path, target=None):
-        if fullname == '_time':
-            return self.builtin.find_spec('time', path, target)
-        if fullname in ['random', 'math']:
+        if fullname == "_time":
+            return self.builtin.find_spec("time", path, target)
+        if fullname in ["random", "math"]:
             return self.builtin.find_spec(fullname, path, target)
-        if fullname in ['json']:
+        if fullname in ["json"]:
             sys_path_saved = sys.path
             sys.path = sys_path_orig
             return self.pathfinder.find_spec(fullname, path, target)
             sys.path = sys_path_saved
 
 
-#sys.meta_path.insert(0, Hook())
+# sys.meta_path.insert(0, Hook())
 
 sys.path = [
-    os.path.join(projectpath, 'python_payload'),
-    os.path.join(projectpath, 'sim', 'fakes'),
+    os.path.join(projectpath, "python_payload"),
+    os.path.join(projectpath, "sim", "fakes"),
 ]
 
 builtin = BuiltinImporter()
@@ -49,13 +49,14 @@ sys.meta_path = [pathfinder, underscore]
 
 # Clean up whatever might have already been imported as `time`.
 import time
-print('aaaa', time)
+
+print("aaaa", time)
 importlib.reload(time)
-print('bbbb', time)
+print("bbbb", time)
 
 sys.path_importer_cache.clear()
 importlib.invalidate_caches()
 
-sys.modules['time'] = time
+sys.modules["time"] = time
 
-import main
\ No newline at end of file
+import main
diff --git a/tools/codequal-report.py b/tools/codequal-report.py
index ecab2c534230839c225b8632415310d10a0d5033..7bdefd038377b48da4db9dc9d7308af46da0357b 100644
--- a/tools/codequal-report.py
+++ b/tools/codequal-report.py
@@ -50,13 +50,13 @@ class Issue:
     fingerprint: str
 
 
-def parse_line(s: str, nocol: bool=False) -> Union[Issue, None]:
+def parse_line(s: str, nocol: bool = False) -> Union[Issue, None]:
     nparts = 4
     if nocol:
         nparts = 3
-    parts = s.split(':', nparts)
+    parts = s.split(":", nparts)
     path = parts[0]
-    path = path.removeprefix(os.getcwd() + '/')
+    path = path.removeprefix(os.getcwd() + "/")
     line = int(parts[1])
     if nocol:
         col = None
@@ -67,17 +67,25 @@ def parse_line(s: str, nocol: bool=False) -> Union[Issue, None]:
         col = int(parts[2])
         rest = parts[4].strip()
     severity: Severity = {
-        'warning': Severity.major,
-        'error': Severity.blocker,
+        "warning": Severity.major,
+        "error": Severity.blocker,
     }.get(level, Severity.info)
-    check = ''
-    if rest.endswith(']'):
-        rest, check = rest.split('[')
+    check = ""
+    if rest.endswith("]"):
+        rest, check = rest.split("[")
         rest = rest.strip()
-        check = check.rstrip(']')
-    location = Location(path=path, positions=Positions(begin=Position(line=line, column=col)))
-    fp = hashlib.md5(f'{check} {path} {line}'.encode()).hexdigest()
-    return Issue(description=rest, check_name=check, severity=severity, location=location, fingerprint=fp)
+        check = check.rstrip("]")
+    location = Location(
+        path=path, positions=Positions(begin=Position(line=line, column=col))
+    )
+    fp = hashlib.md5(f"{check} {path} {line}".encode()).hexdigest()
+    return Issue(
+        description=rest,
+        check_name=check,
+        severity=severity,
+        location=location,
+        fingerprint=fp,
+    )
 
 
 def mypy(p: str) -> List[Issue]:
@@ -85,9 +93,9 @@ def mypy(p: str) -> List[Issue]:
     with open(p) as f:
         for line in f:
             line = line.strip()
-            if line.startswith('Found '):
+            if line.startswith("Found "):
                 continue
-            if line.startswith('Success: '):
+            if line.startswith("Success: "):
                 continue
             v = parse_line(line, nocol=True)
             if v is not None:
@@ -103,7 +111,7 @@ def clang_tidy(p: str) -> List[Issue]:
         in_context = False
         for line in f:
             line = line.strip()
-            if line == 'Enabled checks:':
+            if line == "Enabled checks:":
                 in_checks = True
                 continue
 
@@ -113,7 +121,7 @@ def clang_tidy(p: str) -> List[Issue]:
                 continue
 
             if in_list:
-                if line.split()[0].endswith('clang-tidy'):
+                if line.split()[0].endswith("clang-tidy"):
                     in_context = False
                     continue
                 if not in_context:
@@ -132,9 +140,9 @@ def main() -> None:
 
     kind = sys.argv[1]
     path = sys.argv[2]
-    if kind == 'clang-tidy':
+    if kind == "clang-tidy":
         res = clang_tidy(path)
-    elif kind == 'mypy':
+    elif kind == "mypy":
         res = mypy(path)
     else:
         sys.stderr.write(f"Unknown kind {kind}\n")
@@ -145,5 +153,6 @@ def main() -> None:
     if res != []:
         sys.exit(1)
 
-if __name__ == '__main__':
+
+if __name__ == "__main__":
     main()