Compare commits
4 Commits
1181759ace
...
main
Author | SHA1 | Date | |
---|---|---|---|
c1bd7d653a | |||
84ff23655c | |||
aabcfc6a9a | |||
1c593aff9b |
31
README.md
31
README.md
@ -64,6 +64,9 @@ arithmetic via bounded, clamped, and wrapped integer types.
|
|||||||
```text
|
```text
|
||||||
src/
|
src/
|
||||||
├── main.rs Entry point of the application.
|
├── main.rs Entry point of the application.
|
||||||
|
├── menu/ The Menu Applicaiton.
|
||||||
|
├── badge/ The Badge Application.
|
||||||
|
├── snake/ The Snake Application.
|
||||||
```
|
```
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
@ -93,8 +96,36 @@ To build and flash the program to your Microbit just run:
|
|||||||
cargo embed
|
cargo embed
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
To generate all the documentation you will need to have pandoc and weasyprint
|
||||||
|
installed.
|
||||||
|
|
||||||
|
### Design Doc
|
||||||
|
|
||||||
|
The [Design Doc][./docs/design.pdf] is generated with pandoc from the markdown
|
||||||
|
file.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pandoc ./docs/design.md --pdf-engine=weasyprint -o ./docs/design.pdf
|
||||||
|
```
|
||||||
|
|
||||||
|
### Software Design Doc
|
||||||
|
|
||||||
|
The [Software Design Doc][./docs/sdd.pdf] is generated with pandoc from the markdown
|
||||||
|
file.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pandoc ./docs/sdd.md --pdf-engine=weasyprint -o ./docs/sdd.pdf
|
||||||
|
```
|
||||||
|
|
||||||
|
### UML
|
||||||
|
|
||||||
|
[UML][./docs/uml/] is generated using Plant UML on the \*.puml files.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
plantuml ./docs/uml/*.puml
|
||||||
|
```
|
||||||
---
|
---
|
||||||
|
|
||||||
## Copyright & License
|
## Copyright & License
|
||||||
|
264
docs/prd.md
Normal file
264
docs/prd.md
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
# MicroBadge
|
||||||
|
## Product Design Document
|
||||||
|
**Version:** 1.0
|
||||||
|
**Date:** July 11, 2025
|
||||||
|
**Author(s):** CyberMages, LLC (Jason Smith)
|
||||||
|
**Stakeholders:** Self, Potential Conference Attendees, Hobbyists
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
1. [Introduction](#introduction)
|
||||||
|
- [Purpose of this Document](#purpose-of-this-document)
|
||||||
|
- [Product Overview](#product-overview)
|
||||||
|
- [Target Audience](#target-audience)
|
||||||
|
- [Scope](#scope)
|
||||||
|
2. [Business Case & Goals](#business-case-goals)
|
||||||
|
- [Problem Statement](#problem-statement)
|
||||||
|
- [Business Objectives](#business-objectives)
|
||||||
|
- [Key Performance Indicators (KPIs)](#key-performance-indicators-kpis)
|
||||||
|
3. [User Stories / Use Cases / Features](#user-stories-use-cases-features)
|
||||||
|
- [User Personas](#user-personas)
|
||||||
|
- [Core Features](#core-features)
|
||||||
|
* [Menu System](#menu-system)
|
||||||
|
* [Name Scroller](#name-scroller)
|
||||||
|
* [NFC Business Card](#nfc-business-card)
|
||||||
|
* [Snake Game](#snake-game)
|
||||||
|
- [Out-of-Scope Features](#out-of-scope-features)
|
||||||
|
4. [User Experience (UX) & User Interface (UI)](#user-experience-ux-user-interface-ui)
|
||||||
|
- [User Flows](#user-flows)
|
||||||
|
- [Wireframes / Mockups](#wireframes-mockups)
|
||||||
|
- [Interaction Design](#interaction-design)
|
||||||
|
- [Accessibility Considerations](#accessibility-considerations)
|
||||||
|
- [Brand & Style Guidelines](#brand-style-guidelines)
|
||||||
|
5. [Technical Considerations (High-Level)](#technical-considerations-high-level)
|
||||||
|
- [System Integrations](#system-integrations)
|
||||||
|
- [Performance Requirements](#performance-requirements)
|
||||||
|
- [Security Considerations](#security-considerations)
|
||||||
|
- [Data Privacy](#data-privacy)
|
||||||
|
6. [Release Plan & Roadmap](#release-plan-roadmap)
|
||||||
|
- [Phased Rollout Strategy](#phased-rollout-strategy)
|
||||||
|
- [Future Considerations / Roadmap](#future-considerations-roadmap)
|
||||||
|
7. [Success Metrics & Analytics](#success-metrics-analytics)
|
||||||
|
- [Key Metrics to Track](#key-metrics-to-track)
|
||||||
|
- [Analytics Tools](#analytics-tools)
|
||||||
|
8. [Open Questions and Assumptions](#open-questions-and-assumptions)
|
||||||
|
- [Open Questions](#open-questions)
|
||||||
|
- [Assumptions](#assumptions)
|
||||||
|
9. [Appendices](#appendices)
|
||||||
|
- [Glossary](#glossary)
|
||||||
|
- [References](#references)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
### Purpose of this Document
|
||||||
|
This document defines the **product vision**, **features**, and **user
|
||||||
|
experience** for MicroBadge, an interactive name badge application, to guide
|
||||||
|
its development and align on its purpose.
|
||||||
|
|
||||||
|
### Product Overview
|
||||||
|
**MicroBadge** is an interactive embedded application built for the BBC
|
||||||
|
micro:bit v2, functioning as a **conference name badge**. It provides a
|
||||||
|
**professional and technical icebreaker** at events through various
|
||||||
|
interactive apps.
|
||||||
|
|
||||||
|
### Target Audience
|
||||||
|
* Professionals attending conferences and networking events.
|
||||||
|
* Individuals looking for unique icebreakers and conversation starters.
|
||||||
|
* Developers interested in embedded Rust and interactive hardware.
|
||||||
|
* Anyone seeking a personalized, memorable name badge experience.
|
||||||
|
|
||||||
|
### Scope
|
||||||
|
This document covers the **initial release** of MicroBadge, including its
|
||||||
|
core menu system, name scroller, Snake game, and the NFC business card
|
||||||
|
functionality.
|
||||||
|
|
||||||
|
## Business Case & Goals
|
||||||
|
### Problem Statement
|
||||||
|
* Traditional name badges are often static and unengaging, failing
|
||||||
|
to facilitate professional or technical icebreaking effectively.
|
||||||
|
* Networking often lacks memorable, interactive elements.
|
||||||
|
* Sharing contact information can be cumbersome.
|
||||||
|
|
||||||
|
### Business Objectives
|
||||||
|
* Provide a **custom and memorable name badge experience**.
|
||||||
|
* Enable **fun interactions** and **easy sharing of contact info via NFC**.
|
||||||
|
* Serve as a **technical portfolio piece** for conferences, meetings,
|
||||||
|
and interviews.
|
||||||
|
* **Showcase embedded Rust development** using async and no-std.
|
||||||
|
|
||||||
|
### Key Performance Indicators (KPIs)
|
||||||
|
* Number of positive comments received about the badge.
|
||||||
|
* Frequency of badge-initiated conversations.
|
||||||
|
* Successful NFC contact transfers (post-completion).
|
||||||
|
* Completion rate of the Snake game by others.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## User Stories / Use Cases / Features
|
||||||
|
### User Personas
|
||||||
|
* **Conference Attendee Alex:** Wants to easily display their name,
|
||||||
|
engage in lighthearted interactions, and quickly share contact
|
||||||
|
details without fumbling for cards.
|
||||||
|
* **Tech Enthusiast Tara:** Appreciates the technical sophistication
|
||||||
|
and wants to use the badge as a conversation starter about embedded
|
||||||
|
Rust.
|
||||||
|
|
||||||
|
### Core Features
|
||||||
|
#### Menu System
|
||||||
|
**Description:** Allows the user to switch between different
|
||||||
|
applications on the micro:bit.
|
||||||
|
|
||||||
|
**User Stories:** As a user, I want to easily navigate between different
|
||||||
|
badge functionalities so I can quickly access the app
|
||||||
|
I need.
|
||||||
|
|
||||||
|
**Acceptance Criteria:**
|
||||||
|
* Menu is visible on the LED matrix.
|
||||||
|
* Navigation via physical buttons is intuitive and responsive.
|
||||||
|
* Selecting an app loads it promptly.
|
||||||
|
|
||||||
|
**Priority:** Must Have
|
||||||
|
|
||||||
|
#### Name Scroller
|
||||||
|
**Description:** Scrolls a user-defined name or custom message
|
||||||
|
across the 5x5 LED matrix.
|
||||||
|
|
||||||
|
**User Stories:** As a conference attendee, I want my name to scroll across
|
||||||
|
the badge so others can easily identify me from a distance.
|
||||||
|
|
||||||
|
**Acceptance Criteria:**
|
||||||
|
* Name scrolls smoothly and is legible.
|
||||||
|
* Scrolling text supports English ASCII characters only.
|
||||||
|
* Speed and repeat mode are configurable (future state).
|
||||||
|
|
||||||
|
**Priority:** Must Have
|
||||||
|
|
||||||
|
#### NFC Business Card
|
||||||
|
**Description:** Leverages the onboard NFC peripheral to share vCard/contact
|
||||||
|
data with mobile phones.
|
||||||
|
|
||||||
|
**User Stories:** As a user, I want to quickly share my contact information
|
||||||
|
by tapping my badge on a phone, saving time and effort.
|
||||||
|
|
||||||
|
**Acceptance Criteria:**
|
||||||
|
* Badge emits vCard data via NFC upon activation.
|
||||||
|
* Mobile phones can successfully read and import the data.
|
||||||
|
|
||||||
|
**Priority:** Must Have
|
||||||
|
|
||||||
|
#### Snake Game
|
||||||
|
**Description:** A classic Snake game playable on the 5x5 LED display,
|
||||||
|
designed for fun and interactivity.
|
||||||
|
|
||||||
|
**User Stories:** As a user, I want a simple, engaging game on my badge to
|
||||||
|
break the ice or pass time.
|
||||||
|
|
||||||
|
**Acceptance Criteria:**
|
||||||
|
* Game renders correctly on the 5x5 LED matrix.
|
||||||
|
* Controls (Button A, Button B for turning) are responsive.
|
||||||
|
* Game includes food, score tracking, and game over conditions.
|
||||||
|
* Game speed is tuned for usability.
|
||||||
|
|
||||||
|
**Priority:** Should Have
|
||||||
|
|
||||||
|
### Out-of-Scope Features
|
||||||
|
* Configuration storage via flash memory.
|
||||||
|
* Desktop companion app for editing settings.
|
||||||
|
* BLE for data sync or configuration.
|
||||||
|
|
||||||
|
## User Experience (UX) & User Interface (UI)
|
||||||
|
### User Flows
|
||||||
|
* **Power On:** Device boots, then goes directly to the main menu.
|
||||||
|
* **App Selection:** From main menu, user presses Button A to cycle
|
||||||
|
through apps, Button B to select.
|
||||||
|
* **App Interaction:** User interacts with the active app (e.g.,
|
||||||
|
scrolling name, playing Snake).
|
||||||
|
* **Return to Menu:** Pressing the **Reset button** on the back of
|
||||||
|
the device returns to the main menu.
|
||||||
|
|
||||||
|
### Wireframes / Mockups
|
||||||
|
The primary UI is the **5x5 LED matrix**. Visuals are abstract patterns or
|
||||||
|
simple character representations. (No detailed wireframes beyond conceptual
|
||||||
|
understanding of 5x5 limits).
|
||||||
|
|
||||||
|
### Interaction Design
|
||||||
|
* `Button A`: Navigation (e.g., move down in menu, turn left in Snake).
|
||||||
|
* `Button B`: Selection (e.g., select app, turn right in Snake).
|
||||||
|
* `Start Button` (capacitive touch logo): Its function varies by app:
|
||||||
|
- In the **Menu**, it selects the currently highlighted application.
|
||||||
|
- In the **Name Scroller**, pressing any button (A, B, or Start)
|
||||||
|
will return to the main menu.
|
||||||
|
- In the **Snake game**, the Start button is used for selections
|
||||||
|
within the game (e.g., choosing difficulty).
|
||||||
|
* LED matrix provides immediate **visual feedback** for selections, game
|
||||||
|
states, and menu navigation.
|
||||||
|
|
||||||
|
### Accessibility Considerations
|
||||||
|
Limited by the 5x5 LED matrix. Focus is on **clear, distinct visual
|
||||||
|
patterns** where possible.
|
||||||
|
|
||||||
|
### Brand & Style Guidelines
|
||||||
|
Adheres to the physical aesthetic of the BBC micro:bit v2, with simple,
|
||||||
|
functional LED display patterns.
|
||||||
|
|
||||||
|
## Technical Considerations (High-Level)
|
||||||
|
### System Integrations
|
||||||
|
* Onboard NFC peripheral (for NFC Business Card app).
|
||||||
|
* GPIO for button input.
|
||||||
|
* LED matrix display control.
|
||||||
|
|
||||||
|
### Performance Requirements
|
||||||
|
* Menu navigation must be responsive.
|
||||||
|
* Snake game refresh rate tuned for smooth play.
|
||||||
|
|
||||||
|
### Security Considerations
|
||||||
|
NFC data transfer should minimize privacy risks (e.g., only share public
|
||||||
|
contact info). No sensitive data stored.
|
||||||
|
|
||||||
|
### Data Privacy
|
||||||
|
VCard data intended for public sharing only. No personal data collected or
|
||||||
|
stored by the application itself.
|
||||||
|
|
||||||
|
## Release Plan & Roadmap
|
||||||
|
### Phased Rollout Strategy
|
||||||
|
Initial single release. No phased rollout planned for this version.
|
||||||
|
|
||||||
|
### Future Considerations / Roadmap
|
||||||
|
* Finalize NFC vCard transmission.
|
||||||
|
* Add configuration storage via flash memory for user preferences.
|
||||||
|
* Create a desktop companion app for easier settings editing.
|
||||||
|
* Support BLE for data synchronization or advanced configuration.
|
||||||
|
|
||||||
|
## Success Metrics & Analytics
|
||||||
|
### Key Metrics to Track
|
||||||
|
As listed in section 4.3 (e.g., qualitative feedback, observations of
|
||||||
|
interaction, NFC transfer success rate).
|
||||||
|
|
||||||
|
### Analytics Tools
|
||||||
|
Primarily anecdotal observation and direct user feedback due to the
|
||||||
|
embedded, standalone nature of the device.
|
||||||
|
|
||||||
|
## Open Questions and Assumptions
|
||||||
|
### Open Questions
|
||||||
|
* Exact vCard data format for NFC compatibility across devices.
|
||||||
|
* Optimal user experience for NFC activation on the micro:bit.
|
||||||
|
|
||||||
|
### Assumptions
|
||||||
|
* Users will be familiar with basic micro:bit interactions.
|
||||||
|
* The 5x5 LED matrix provides sufficient visual fidelity for intended
|
||||||
|
applications.
|
||||||
|
* NFC peripheral provides reliable data transfer.
|
||||||
|
|
||||||
|
## Appendices
|
||||||
|
### Glossary
|
||||||
|
**Embassy:** An asynchronous embedded runtime for Rust.
|
||||||
|
**HALs:** Hardware Abstraction Layers, providing a consistent API for
|
||||||
|
hardware peripherals.
|
||||||
|
**micro:bit v2:** A small, programmable computer designed for
|
||||||
|
education and hobbyists.
|
||||||
|
**NFC:** Near Field Communication, a set of communication protocols.
|
||||||
|
**PWM:** Pulse-width modulation, used for controlling LED intensity.
|
||||||
|
**vCard:** An electronic business card file format.
|
||||||
|
|
||||||
|
### References
|
243
docs/sdd.md
Normal file
243
docs/sdd.md
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
# MicroBadge Software Design Document
|
||||||
|
|
||||||
|
## 1. Introduction
|
||||||
|
|
||||||
|
### 1.1 Purpose
|
||||||
|
|
||||||
|
MicroBadge is a software application suite for the BBC micro:bit v2, designed
|
||||||
|
as a digital conference badge. It serves both functional and social purposes;
|
||||||
|
displaying the user’s name, hosting small interactive demos, and offering
|
||||||
|
contact sharing via NFC.
|
||||||
|
|
||||||
|
This project serves as a conversation starter and technical showcase during
|
||||||
|
events like conferences, meetings, and interviews.
|
||||||
|
|
||||||
|
### 1.2 Scope
|
||||||
|
|
||||||
|
This document focuses exclusively on the software implementation of MicroBadge.
|
||||||
|
It covers the architecture, data structures, behavior, and design choices used
|
||||||
|
to implement the badge’s app-switching system and core applications using Rust
|
||||||
|
and the `embassy` async runtime.
|
||||||
|
|
||||||
|
### 1.3 Audience
|
||||||
|
|
||||||
|
This document is intended for:
|
||||||
|
* Reviewers evaluating its design.
|
||||||
|
* Recruiters or interviewers reviewing technical work.
|
||||||
|
* Anyone trying to learn how to write Rust on an embedded platform.
|
||||||
|
|
||||||
|
## 2. System Overview
|
||||||
|
|
||||||
|
MicroBadge is an embedded application for the micro:bit v2. It uses the
|
||||||
|
Embassy async runtime to manage multiple cooperative tasks without a
|
||||||
|
traditional RTOS. The system is modular and consists of an app switcher,
|
||||||
|
an LED display task, button listeners, and multiple interactive apps.
|
||||||
|
|
||||||
|
### 2.1 Runtime and Concurrency
|
||||||
|
|
||||||
|
MicroBadge uses Embassy's async executor. It runs the following tasks:
|
||||||
|
|
||||||
|
* `display_task` -- Consumes frame buffers and drives the LED matrix.
|
||||||
|
* `button_listener` -- One per button (A, B, Start). Waits for input and
|
||||||
|
debounces it before sending an event.
|
||||||
|
* `app_task` -- Runs the currently selected app. Allows apps to yield and
|
||||||
|
re-enter on each loop.
|
||||||
|
|
||||||
|
All communication is channel-based using `embassy_sync::channel::Channel`.
|
||||||
|
|
||||||
|
[Task UML][./uml/tasks.png]
|
||||||
|
|
||||||
|
### 2.2 App Switcher
|
||||||
|
|
||||||
|
The `Switcher` manages app selection and transition. It displays a menu and
|
||||||
|
uses the A, B, and Start buttons to navigate between apps.
|
||||||
|
|
||||||
|
Each app implements a shared `App` trait with an async `run()` method.
|
||||||
|
Apps are isolated and run cooperatively, returning control when done.
|
||||||
|
|
||||||
|
Current apps:
|
||||||
|
|
||||||
|
* *Menu*. The top-level app that allows selecting from installed apps.
|
||||||
|
* *Badge*. Scrolls a string (e.g. your name) across the LED matrix.
|
||||||
|
* *Snake*. A basic snake game with food, direction control, and score.
|
||||||
|
* *NFC Card* (in development). Will present contact info via NFC.
|
||||||
|
|
||||||
|
[Switcher UML][./uml/switcher.png]
|
||||||
|
|
||||||
|
### 2.3 Input System
|
||||||
|
|
||||||
|
Each button is handled by a separate `button_listener` task. When a button
|
||||||
|
is pressed, it sends a `Button` enum into a shared channel.
|
||||||
|
|
||||||
|
Apps listen for button input using the receiver end of the channel.
|
||||||
|
|
||||||
|
* A and B buttons are mapped to actions like turn left and right.
|
||||||
|
* Start is used to confirm or start an app. It is mapped to the capacitive touch sensor logo.
|
||||||
|
* A debounce delay of 100 ms is used for stability.
|
||||||
|
|
||||||
|
### 2.4 Rendering System
|
||||||
|
|
||||||
|
The rendering system uses a frame buffer that is written by the active app
|
||||||
|
and read by the `display_task`.
|
||||||
|
|
||||||
|
Apps write into this buffer using a `Renderer` abstraction. Drawing is done
|
||||||
|
in an offscreen buffer that is later pushed to the display.
|
||||||
|
|
||||||
|
* The screen is a 5x5 LED grid.
|
||||||
|
* Per-frame updates allow for animations and dynamic content.
|
||||||
|
* LED brightness levels are supported.
|
||||||
|
|
||||||
|
### 2.5 Code Organization
|
||||||
|
|
||||||
|
The system is split into modules for clarity and reuse:
|
||||||
|
|
||||||
|
* `app`. Defines the `App` trait and shared app interface.
|
||||||
|
* `display`. Low-level display driver and LED control.
|
||||||
|
* `renderer`. Provides drawing primitives for apps.
|
||||||
|
* `channel`. Shared async channels for button and frame messages.
|
||||||
|
* `switcher`. App selection logic and switching behavior.
|
||||||
|
* `snake`, `menu`, `badge`. App implementations.
|
||||||
|
* `microbit`. Definitions for button identifiers and device pins.
|
||||||
|
|
||||||
|
Each module is self-contained and uses only the shared channels and traits
|
||||||
|
for interaction.
|
||||||
|
|
||||||
|
## 3. Application Features
|
||||||
|
|
||||||
|
### 3.1 Name Scroller
|
||||||
|
|
||||||
|
* Scrolls a configured name across the LED display.
|
||||||
|
* Uses an async timer to advance frames.
|
||||||
|
* Simple input handling: Any Button returns to the menu.
|
||||||
|
|
||||||
|
### 3.2 Snake Game
|
||||||
|
|
||||||
|
* 5x5 LED grid snake game using a wrapped grid (`WrappedU8<0, 4>`).
|
||||||
|
* Buttons A and B turn the snake left/right.
|
||||||
|
* Food spawns randomly in empty grid cells.
|
||||||
|
* On collision with self, enters game-over state and displays score.
|
||||||
|
|
||||||
|
### 3.3 NFC Business Card (WIP)
|
||||||
|
|
||||||
|
* Intended to broadcast a vCard or custom URI over NFC.
|
||||||
|
* Plan to use the BLE softdevice on the chip.
|
||||||
|
* Currently under development.
|
||||||
|
|
||||||
|
## 4. System Architecture
|
||||||
|
|
||||||
|
This system uses Embassy's async runtime to coordinate application execution,
|
||||||
|
hardware input, and rendering on the micro:bit v2 board. It is divided into
|
||||||
|
distinct tasks: input listeners, a display task, and an app task.
|
||||||
|
|
||||||
|
The overall architecture is message-passing oriented. Input events and screen
|
||||||
|
updates are communicated over embassy channels.
|
||||||
|
|
||||||
|
Application logic is encapsulated in independent modules conforming to a shared
|
||||||
|
`App` trait. The Switcher manages the active app and transitions between them.
|
||||||
|
|
||||||
|
### 4.1 Components
|
||||||
|
|
||||||
|
* `main.rs`: Entry point. Spawns system tasks using Embassy.
|
||||||
|
* `Display`: Renders 5x5 LED frames from a channel receiver using PWM.
|
||||||
|
* `ButtonListener`: Listens for button presses and sends events via channel.
|
||||||
|
* `Switcher`: Manages app lifecycle and transitions.
|
||||||
|
* `App`: Trait for any runnable application module.
|
||||||
|
* `menu`, `badge`, `snake`, `nfc`: App implementations.
|
||||||
|
|
||||||
|
## 5. Data Structures and State
|
||||||
|
|
||||||
|
### 5.1 Position, Direction, and Snake Body
|
||||||
|
|
||||||
|
The board is a fixed 5×5 grid. Positions are stored using a custom `Position`
|
||||||
|
struct, which holds a `ClampedU8` for both `x` and `y` axes, ensuring values
|
||||||
|
remain within bounds.
|
||||||
|
|
||||||
|
* `Position`: Represents a coordinate on the board with safe bounds.
|
||||||
|
* `Direction`: Enum for movement direction: Up, Down, Left, Right.
|
||||||
|
* `Snake`: Maintains a list of `Position` elements representing the snake's
|
||||||
|
body. The first item is always the head.
|
||||||
|
|
||||||
|
Snake direction is updated via input, and movement wraps to stay within the
|
||||||
|
board.
|
||||||
|
|
||||||
|
### 5.2 Message-Passing and Input State
|
||||||
|
|
||||||
|
User input is handled asynchronously via Embassy channels.
|
||||||
|
|
||||||
|
* Button presses are detected using `button_listener` tasks.
|
||||||
|
* Events are sent to the `ButtonChannel`.
|
||||||
|
* Applications read input non-blockingly using `try_receive()`.
|
||||||
|
|
||||||
|
This decouples physical input handling from application logic and allows clean,
|
||||||
|
testable state transitions.
|
||||||
|
|
||||||
|
## 6. Component Interactions
|
||||||
|
|
||||||
|
### 6.1 How Components Interact Over Time
|
||||||
|
|
||||||
|
At runtime, three core tasks are running:
|
||||||
|
|
||||||
|
* `display_task`: Receives rendered frames and presents them on the display.
|
||||||
|
* `button_listener`: Spawns three tasks, one per button (A, B, Start).
|
||||||
|
* `app_task`: Owns the app switcher and runs the current app.
|
||||||
|
|
||||||
|
All interactions are asynchronous and use message-passing over embassy channels.
|
||||||
|
|
||||||
|
### 6.2 Flow of Control
|
||||||
|
|
||||||
|
1. User presses a button.
|
||||||
|
2. The button task sends a message to the channel.
|
||||||
|
3. The app reads the button event from the channel.
|
||||||
|
4. The app updates internal state (e.g., direction or selection).
|
||||||
|
5. The app prepares a frame and sends it to the frame channel.
|
||||||
|
6. The display task renders the frame.
|
||||||
|
|
||||||
|
This loop repeats, giving a responsive, concurrent embedded UI.
|
||||||
|
|
||||||
|
## 7. Development Environment
|
||||||
|
|
||||||
|
### 7.1 Rust + Embassy
|
||||||
|
|
||||||
|
This project uses Rust with the `embassy` async runtime. It provides
|
||||||
|
interrupt-driven, non-blocking execution suitable for low-power embedded
|
||||||
|
devices.
|
||||||
|
|
||||||
|
### 7.2 Tools
|
||||||
|
|
||||||
|
* `probe-rs`: For flashing and debugging firmware.
|
||||||
|
* `defmt`: Lightweight logging for embedded targets.
|
||||||
|
* `panic-probe`: Panic handler integrated with defmt output.
|
||||||
|
* `cargo-embed`: For development workflow and flashing.
|
||||||
|
|
||||||
|
Development was done on Linux using vim and CLI tooling.
|
||||||
|
|
||||||
|
## 8. Design Decisions
|
||||||
|
|
||||||
|
### 8.1 Why Embassy
|
||||||
|
|
||||||
|
Embassy was chosen for its async-first architecture, which maps well to
|
||||||
|
reactive, event-driven embedded applications like games and UI. It allows
|
||||||
|
multiple concurrent tasks without needing an RTOS or blocking code.
|
||||||
|
|
||||||
|
### 8.2 Fixed Board Size
|
||||||
|
|
||||||
|
The micro:bit's 5×5 LED matrix is inherently fixed. Game logic and rendering
|
||||||
|
are simplified by using a constant-size grid, avoiding the need for dynamic
|
||||||
|
allocation or scaling logic.
|
||||||
|
|
||||||
|
### 8.3 Data Wrapping and Clamping
|
||||||
|
|
||||||
|
Out-of-bounds positions are prevented using custom `ClampedU8` types. These
|
||||||
|
provide safe arithmetic that prevents overflow and keeps all positions within
|
||||||
|
0–4 inclusive. This reduces bugs and runtime checks in critical loops.
|
||||||
|
|
||||||
|
## 9. Future Work
|
||||||
|
|
||||||
|
### 9.1 NFC Business Card App
|
||||||
|
|
||||||
|
An in-progress app will emulate a contact card via NFC. The goal is to allow
|
||||||
|
devices to scan the badge and receive contact information, a URL, or a vCard.
|
||||||
|
|
||||||
|
### 9.3 UI Polish
|
||||||
|
|
||||||
|
|
BIN
docs/uml/switcher.png
Normal file
BIN
docs/uml/switcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
35
docs/uml/switcher.puml
Normal file
35
docs/uml/switcher.puml
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
@startuml
|
||||||
|
interface App
|
||||||
|
|
||||||
|
[Switcher] --> [AppID]
|
||||||
|
[Switcher] --> [App] : use
|
||||||
|
|
||||||
|
package "Menu" {
|
||||||
|
[App] <-- [Menu]
|
||||||
|
}
|
||||||
|
|
||||||
|
package "Badge" {
|
||||||
|
[App] <-- [Badge]
|
||||||
|
}
|
||||||
|
|
||||||
|
package "Snake" {
|
||||||
|
[App] <-- [Game]
|
||||||
|
}
|
||||||
|
|
||||||
|
package "NFC" {
|
||||||
|
[App] <-- [NFC]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
package "Channel" {
|
||||||
|
[ButtonReceiver] <-u- [Menu] : use
|
||||||
|
[ButtonReceiver] <-u- [Badge] : use
|
||||||
|
[ButtonReceiver] <-u- [Game] : use
|
||||||
|
[ButtonReceiver] <-u- [NFC] : use
|
||||||
|
[FrameSender] <-u- [Menu] : use
|
||||||
|
[FrameSender] <-u- [Badge] : use
|
||||||
|
[FrameSender] <-u- [Game] : use
|
||||||
|
[FrameSender] <-u- [NFC] : use
|
||||||
|
}
|
||||||
|
|
||||||
|
@enduml
|
BIN
docs/uml/tasks.png
Normal file
BIN
docs/uml/tasks.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
13
docs/uml/tasks.puml
Normal file
13
docs/uml/tasks.puml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
@startuml
|
||||||
|
skinparam componentStyle rectangle
|
||||||
|
[Tasks] --> [Switcher]
|
||||||
|
[Tasks] --> [Display]
|
||||||
|
|
||||||
|
package "Button Listeners" {
|
||||||
|
[Tasks] --> [A Button Listener]
|
||||||
|
[Tasks] --> [B Button Listener]
|
||||||
|
[Tasks] --> [Start Button Listener]
|
||||||
|
}
|
||||||
|
|
||||||
|
@enduml
|
||||||
|
|
Reference in New Issue
Block a user