Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions modules/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
from system.launcher.app import Launcher
from system.power.handler import PowerEventHandler
from system.power.app import PowerManager
from system.boopscreen.app import BoopSpinner

from frontboards.twentyfour import TwentyTwentyFour

# Start the spinning-tilde boop animation
scheduler.start_app(BoopSpinner(), always_on_top=True)

# Start front-board interface
scheduler.start_app(TwentyTwentyFour())
Expand Down
78 changes: 78 additions & 0 deletions modules/system/boopscreen/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
from random import random

from events.input import BUTTON_TYPES, Buttons
from system.eventbus import eventbus
from system.patterndisplay.events import PatternDisable, PatternEnable

import app

from .base.background import Background
from .base.conf import conf
from .base.terminate import terminate
from .common.colour_tools import rgb_from_hue
from .common.led_lighter import LEDLighter
from .boopscreen.logo import Logo


class BoopSpinner(app.App):
"""Spinning Boop Screen."""

def __init__(self):
"""Construct."""
eventbus.emit(PatternDisable())
self.button_states = Buttons(self)
self.hue = random()
self.rotation = conf["rotation"]["start"]
self.fading = False
self.logo = Logo()
self.logo.scale = 0
self.logo.opacity = 1

self.leds = LEDLighter(brightness=conf["leds"]["start"])

def update(self, _):
"""Update."""
self.scan_buttons()
colour = rgb_from_hue(self.hue)

self.logo.grow()
self.logo.colour = colour

self.rotation += conf["rotation"]["rate"]
self.hue += conf["hue-increment"]

if self.logo.full_grown():
self.fading = True

if self.fading:
self.logo.fade()

elif self.leds.brightness < conf["leds"]["max"]:
self.leds.brightness += conf["leds"]["increment"]

self.leds.from_rgb([int(x * 255) for x in colour])

if self.logo.faded():
eventbus.emit(PatternEnable())
terminate(self)

def draw(self, ctx):
"""Draw."""
ctx.rotate(self.rotation)
self.overlays = []
self.overlays.append(
Background(colour=(0, 0, 0), opacity=conf["background-opacity"])
)

self.overlays.append(self.logo)

self.draw_overlays(ctx)

def scan_buttons(self):
"""Buttons."""
if self.button_states.get(BUTTON_TYPES["CANCEL"]):
self.button_states.clear()
terminate(self)


__app_export__ = BoopSpinner
14 changes: 14 additions & 0 deletions modules/system/boopscreen/base/background.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Background:
"""Background."""

def __init__(
self,
colour=(0, 0, 0),
opacity=1,
):
"""Construct."""
self.colour = list(colour) + [opacity]

def draw(self, ctx):
"""Draw ourself."""
ctx.rgba(*self.colour).rectangle(-120, -120, 240, 240).fill()
17 changes: 17 additions & 0 deletions modules/system/boopscreen/base/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
conf = {
"background-opacity": 1,
"bars": {"height": 1.25, "offset": 0.893, "width": 0.223},
"circle": {"radius": 1.0, "ring-width": 0.179},
"fade-rate": 0.1,
"growth-rate": 10,
"hue-increment": 0.03,
"leds": {"increment": 0.02, "start": 0.1, "max": 1.0},
"max-scale": 120,
"rotation": {"rate": 0.3, "start": 2},
"tilde": {
"bottom-curve": [-0.321, -0.125, -0.446, 0.179],
"mid-line": [-0.089, 0.089],
"start": [-0.625, 0.054],
"top-curve": [-0.446, -0.571, 0.089, -0.089],
},
}
7 changes: 7 additions & 0 deletions modules/system/boopscreen/base/terminate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from system.eventbus import eventbus
from system.scheduler.events import RequestStopAppEvent


def terminate(app):
"""Quit the app."""
eventbus.emit(RequestStopAppEvent(app))
87 changes: 87 additions & 0 deletions modules/system/boopscreen/boopscreen/logo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
from math import pi

from ..base.conf import conf


class Logo:
"""The logo."""

def __init__(self, scale=1, colour=None, opacity=1, centre=None):
"""Construct."""
self.scale = scale
self.colour = colour or [1, 1, 1]
self.opacity = opacity
self.centre = centre or (0, 0)

def draw(self, ctx):
"""Draw."""
self.rgba = self.colour + [self.opacity]
ctx.rgba(*self.rgba)

ctx.translate(*self.centre)

for _ in range(2):
self.circle(ctx)
self.bars(ctx)
self.tilde(ctx)
ctx.rotate(pi)

ctx.fill()

def circle(self, ctx):
"""Draw the circle."""
ctx.rgba(*self.rgba)
ctx.arc(0, 0, conf["circle"]["radius"] * self.scale, pi, 0, True)

ctx.arc(
0,
0,
(conf["circle"]["radius"] - conf["circle"]["ring-width"]) * self.scale,
0,
pi,
False,
)

ctx.close_path()

def bars(self, ctx):
"""Draw the bars."""
horizontal_offset = (conf["bars"]["width"] / 2) * self.scale
vertical_offset = conf["bars"]["offset"] * self.scale
height = (conf["bars"]["height"] + conf["bars"]["offset"]) * self.scale

ctx.move_to(-horizontal_offset, -height)
ctx.line_to(-horizontal_offset, -vertical_offset)
ctx.line_to(horizontal_offset, -vertical_offset)
ctx.line_to(horizontal_offset, -height)
ctx.close_path()

def tilde(self, ctx):
"""Draw the ~."""
ctx.move_to(*scale_list(conf["tilde"]["start"], self.scale))
ctx.quad_to(*scale_list(conf["tilde"]["top-curve"], self.scale))
ctx.line_to(*scale_list(conf["tilde"]["mid-line"], self.scale))
ctx.quad_to(*scale_list(conf["tilde"]["bottom-curve"], self.scale))

ctx.close_path()

def fade(self, amount=conf["fade-rate"]):
"""Fade."""
self.opacity -= amount

def faded(self, limit=0):
"""Are we faded-out?"""
return self.opacity <= limit

def grow(self, amount=conf["growth-rate"]):
"""Grow."""
self.scale += amount

def full_grown(self, limit=conf["max-scale"]):
"""Are we big?"""
return self.scale > limit


def scale_list(items, scale):
"""Scale some numbers."""
return [x * scale for x in items]
44 changes: 44 additions & 0 deletions modules/system/boopscreen/common/colour_tools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from math import floor


def _get_segments():
"""Get the segments."""
pattern = [1, None, 0, 0, None, 1]
offsets = {"red": 0, "blue": 2, "green": 4}

segments = []
for i in range(6):
segments.append({"offset": i * 60})
for component, offset in offsets.items():
index = (i + offset) % len(
pattern
) # because `deque` isn't the same in micropython
if pattern[index] is not None:
segments[-1][component] = pattern[index]

return segments


_segments = _get_segments()


def _get_sector(degrees):
"""Determine which sector we're in."""
return floor(degrees / 60)


def _rgb_from_degrees(degrees):
"""Get RGB from degrees of rotation."""
sector = _get_sector(degrees)
segment = _segments[sector]
offset = (1 / 60) * (degrees - segment["offset"])

if sector % 2 == 1:
offset = 1 - offset

return [segment.get(x, offset) for x in ["red", "green", "blue"]]


def rgb_from_hue(decimal):
"""Get RGB from hue value (0.0 - 1.0)."""
return _rgb_from_degrees((decimal * 360) % 360)
55 changes: 55 additions & 0 deletions modules/system/boopscreen/common/led_lighter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from tildagonos import tildagonos

from .colour_tools import rgb_from_hue


class LEDLighter:
"""Light some LEDs."""

def __init__(self, brightness):
"""Construct."""
self.brightness = brightness

def light(self, hue, secondary_hue=None):
"""Light lights."""
colour = rgb_from_hue(hue)
for i in range(18):
if secondary_hue and i > 11:
colour = rgb_from_hue(secondary_hue)
tildagonos.leds[i + 1] = [
gamma_corrections[int(i * 255 * self.brightness)] for i in colour
]

tildagonos.leds.write()

def from_rgb(self, rgb, secondary_rgb=None):
"""Light lights from an RGB."""
colour = rgb
for i in range(12):
tildagonos.leds[i + 1] = [
gamma_corrections[int(i * self.brightness)] for i in colour
]

tildagonos.leds.write()


# fmt: off
gamma_corrections = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,
5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,
10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 109, 110, 112, 114,
115, 117, 119, 120, 122, 124, 126, 127, 129, 131, 133, 135, 137, 138, 140, 142,
144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 167, 169, 171, 173, 175,
177, 180, 182, 184, 186, 189, 191, 193, 196, 198, 200, 203, 205, 208, 210, 213,
215, 218, 220, 223, 225, 228, 231, 233, 236, 239, 241, 244, 247, 249, 252, 255
]
# fmt: on
Loading