Skip to content
Snippets Groups Projects
Select Git revision
  • 61c4faab66dc125d83847d01e87f443f9d6e4ccf
  • master default protected
  • ws2812_docs_work
  • ws2812_module_work
  • genofire/ble-card10-timeread
  • schneider/fundamental-test
  • schneider/ble-buffers
  • ios-workarounds
  • schneider/maxim-sdk-update
  • rahix/simple_menu
  • ch3/splashscreen
  • koalo/bhi160-works-but-dirty
  • koalo/wip/i2c-for-python
  • renze/safe_mode
  • renze/hatchery_apps
  • koalo/factory-reset
  • msgctl/gfx_rle
  • msgctl/faultscreen
  • msgctl/textbuffer_api
  • schneider/bonding
  • schneider/bootloader-update-9a0d158
  • v1.5
  • v1.4
  • v1.3
  • v1.2
  • v1.1
  • v1.0
  • release-1
  • bootloader-v1
  • v0.0
30 results

DEV_Config.c

Blame
  • Forked from card10 / firmware
    Source project has a limited visibility.
    about.py 9.05 KiB
    from ctx import Context
    from st3m import InputState, Responder
    from st3m.ui.view import BaseView, ViewTransitionSwipeRight
    from st3m.utils import tau, sd_card_plugged
    from st3m.goose import List, Optional
    import math
    import os
    
    
    class Screen(Responder):
        """
        A screen with some text. Just the text part, without background.
        """
    
        START_Y = -50
        FONT = "Camp Font 3"
        FONT_SIZE = 15
    
        def __init__(self, text: List[str]) -> None:
            self.text = text
    
        def draw(self, ctx: Context) -> None:
            ctx.font = self.FONT
            ctx.font_size = self.FONT_SIZE
            ctx.text_baseline = ctx.MIDDLE
    
            y = self.START_Y
            for line in self.text:
                ctx.move_to(0, y)
                ctx.text(line)
                y += self.FONT_SIZE
    
        def think(self, ins: InputState, delta_ms: int) -> None:
            pass
    
    
    class HeroScreen(Screen):
        """
        A screen with large text in the middle.
        """
    
        START_Y = 0
        FONT = "Camp Font 2"
        FONT_SIZE = 30
    
    
    class IntroScreen(Screen):
        """
        Title card which shows on About app startup.
        """
    
        START_Y = 25
    
        def __init__(self) -> None:
            super().__init__(["Chaos", "Communication", "Camp 2023"])
    
        def draw(self, ctx: Context) -> None:
            ctx.text_align = ctx.MIDDLE
    
            ctx.font = "Camp Font 2"
            ctx.font_size = 50
    
            ctx.move_to(0, -33)
            ctx.text("flow3r")
            ctx.move_to(0, -3)
            ctx.text("badge")
    
            super().draw(ctx)
    
    
    class SpaceScreen(Screen):
        """
        Card which shows Flash and SD storage space.
        """
    
        def __init__(self) -> None:
            flash_statvfs = os.statvfs("/flash")
            flash_free = flash_statvfs[1] * flash_statvfs[3]
            flash_total = flash_statvfs[1] * flash_statvfs[2]
            self.flash_used_percentage = (
                (100 - ((flash_free / flash_total) * 100)) if flash_free != 0 else 0
            )
    
            self.sd_plugged = sd_card_plugged()
            if not self.sd_plugged:
                sd_free = 0
                sd_total = 0
                self.sd_used_percentage = 0
            else:
                sd_statvfs = os.statvfs("/sd")
                sd_free = sd_statvfs[1] * sd_statvfs[3]
                sd_total = sd_statvfs[1] * sd_statvfs[2]
                self.sd_used_percentage = (
                    (100 - ((sd_free / sd_total) * 100)) if sd_free != 0 else 0
                )
    
            self.flash_text = f"{self._get_pretty_size(flash_total - flash_free)}/{self._get_pretty_size(flash_total)}"
            self.sd_text = f"{self._get_pretty_size(sd_total - sd_free)}/{self._get_pretty_size(sd_total)}"
    
        def _draw_bar(self, ctx, x, y, width, height, color):
            ctx.save()
            ctx.arc(x, y + (height / 2), height / 2, 0, math.tau, 0)
            ctx.rectangle(x, y, width, height)
            ctx.arc(x + width, y + (height / 2), height / 2, 0, math.tau, 0)
            ctx.rgb(*color)
            ctx.fill()
            ctx.restore()
    
        def _draw_percentage_bar(
            self, ctx, x, y, width, height, bg_color, fg_color, percentage
        ):
            self._draw_bar(ctx, x, y, width, height, bg_color)
            self._draw_bar(ctx, x, y, (width / 100) * percentage, height, fg_color)
    
        def _get_pretty_size(self, byte_count: int) -> str:
            MiB = 1024 * 1024
            GiB = MiB * 1024
    
            # if over 2GiB, return GiB numbers, else return MiB
            if byte_count > (2 * GiB):
                return "{:.2f}GiB".format(byte_count / GiB)
            else:
                return "{:.2f}MiB".format(byte_count / MiB)
    
        def draw(self, ctx: Context) -> None:
            ctx.font = "Camp Font 2"
            ctx.text_align = ctx.MIDDLE
            ctx.font_size = 30
    
            # Flash
            ctx.move_to(0, -38)
            ctx.text("Flash")
    
            self._draw_percentage_bar(
                ctx,
                -65,
                -31,
                130,
                6,
                (0, 0, 0),
                (1, 1, 1),
                self.flash_used_percentage,
            )
            ctx.font = "Camp Font 3"
            ctx.font_size = 15
            ctx.move_to(0, -10)
            ctx.text(self.flash_text)
    
            # SD
            ctx.font_size = 30
            ctx.move_to(0, 23)
            ctx.font = "Camp Font 2"
            if self.sd_plugged:
                ctx.text("SD Card")
            else:
                ctx.text("No SD Detected")
    
            self._draw_percentage_bar(
                ctx,
                -65,
                30,
                130,
                6,
                (0, 0, 0),
                (1, 1, 1),
                self.sd_used_percentage,
            )
            ctx.font = "Camp Font 3"
            ctx.font_size = 15
            ctx.move_to(0, 51)
            ctx.text(self.sd_text)
    
    
    class About(BaseView):
        """
        A pseudo-app (applet?) which displays an about screen for the badge.
        """
    
        def __init__(self) -> None:
            self.ts = 0.0
            self.screens: List[Screen] = [
                IntroScreen(),
                SpaceScreen(),
                HeroScreen(
                    [
                        "flow3r.garden",
                    ]
                ),
                Screen(
                    [
                        "This is Free",
                        "Software based on",
                        "code by numerous",
                        "third parties.",
                        "",
                        "Visit",
                        "flow3r.garden/license",
                        "for more info.",
                    ]
                ),
            ]
            self.screen_ix = 0
            self.screen_ix_anim = 0.0
            super().__init__()
    
        def think(self, ins: InputState, delta_ms: int) -> None:
            super().think(ins, delta_ms)
            self.ts += delta_ms / 1000
    
            # Change target screen intent.
            if self.input.buttons.app.left.pressed and self._can_left():
                self.screen_ix -= 1
            if self.input.buttons.app.right.pressed and self._can_right():
                self.screen_ix += 1
    
            # Calculate animation/transitions.
            diff = self.screen_ix - self.screen_ix_anim
            if abs(diff) < 0.01:
                self.screen_ix_anim = self.screen_ix
            else:
                if diff > 0:
                    diff = min(diff, 10 * (delta_ms / 1000))
                else:
                    diff = max(diff, -10 * (delta_ms / 1000))
                self.screen_ix_anim += diff
    
        def _can_left(self, ix: Optional[int] = None) -> bool:
            """
            Returns true if the given screen index (or the current screen index) can
            be decreased.
            """
            if ix is None:
                ix = self.screen_ix
            return ix > 0
    
        def _can_right(self, ix: Optional[int] = None) -> bool:
            """
            Returns true if the given screen index (or the current screen index) can
            be increased.
            """
            if ix is None:
                ix = self.screen_ix
            return ix < len(self.screens) - 1
    
        def draw(self, ctx: Context) -> None:
            # Background
            ctx.rectangle(-120, -120, 240, 240)
            ctx.rgb(117 / 255, 255 / 255, 226 / 255)
            ctx.fill()
    
            ctx.arc(0, 350, 300, 0, tau, 0)
            ctx.rgb(61 / 255, 165 / 255, 30 / 255)
            ctx.fill()
    
            ctx.save()
            y = -40 + math.cos(self.ts * 2 + 10) * 10
            ctx.translate(0, y)
            for i in range(5):
                a = i * tau / 5 + self.ts
                size = 30 + math.cos(self.ts) * 5
                ctx.save()
                ctx.rotate(a)
                ctx.translate(30, 0)
                ctx.arc(0, 0, size, 0, tau, 0)
                ctx.gray(1)
                ctx.fill()
                ctx.restore()
    
            ctx.arc(0, 0, 20, 0, tau, 0)
            ctx.rgb(255 / 255, 247 / 255, 46 / 255)
            ctx.fill()
            ctx.restore()
    
            # Prepare list of screens to draw. We draw at most two screens if we're
            # in a transition, otherwies just one.
            #
            # List of (screen index, screen object, draw offset) tuples.
            draw = []
    
            diff = self.screen_ix - self.screen_ix_anim
            if diff > 0.01 or diff < -0.01:
                ix = math.floor(self.screen_ix_anim)
                draw = [
                    (ix, self.screens[ix], self.screen_ix_anim - ix),
                    (ix + 1, self.screens[ix + 1], (self.screen_ix_anim - ix) - 1),
                ]
            else:
                draw = [
                    (self.screen_ix, self.screens[self.screen_ix], 0),
                ]
    
            # Draw currently visible screens.
            for ix, screen, offs in draw:
                ctx.save()
                ctx.translate(-240 * offs, 0)
    
                # Opaque circle
                ctx.save()
                ctx.global_alpha = 0.5
                ctx.rgb(0, 0, 0)
                ctx.arc(0, 0, 90, 0, tau, 0)
                ctx.fill()
    
                # Draw arrows.
                if self._can_left(ix):
                    ctx.move_to(-105, 15)
                    ctx.font = "Material Icons"
                    ctx.font_size = 30
                    ctx.text_align = ctx.MIDDLE
                    ctx.text("\ue5c4")
                if self._can_right(ix):
                    ctx.move_to(105, 15)
                    ctx.font = "Material Icons"
                    ctx.font_size = 30
                    ctx.text_align = ctx.MIDDLE
                    ctx.text("\ue5c8")
                ctx.restore()
    
                # Text
                ctx.save()
                ctx.global_alpha = 1.0
                ctx.gray(1)
    
                ctx.text_align = ctx.MIDDLE
    
                screen.draw(ctx)
    
                ctx.restore()
                ctx.restore()