a carry device. built from scratch on the board of a budget smartwatch, designed to hang from a belt loop, a bag or a set of keys.
the idea
a watch is worn and glanced at. a carried object is noticed by other people, held by its owner and used for a few seconds at a time. fob is designed for that second life.
principles
| principle | what it means on the device |
|---|---|
| one switch | the crown is the only button. rotate, press, press twice, hold. the whole vocabulary fits in one minute and works without looking. |
| ambient first | the device spends nearly all of its life at rest on a belt. the resting state is designed before any mode. |
| quiet by default | the interface is monochrome: bone-white ink on black. colour comes from content (photographs, drawings, pixel art). one signal colour is reserved for what is waiting on you. |
| continuity | every mode remembers its last page. double-press returns to the dial; the next press returns to exactly where you were. |
| nothing invented | every value shown is read from a real source. if a source is unavailable, that piece is left out rather than faked. |
| motion is the product | springs, interruptible gestures, haptics landing on the same frame as the visual settle. a small interface that feels expensive. |
| paper first | every screen is sketched by hand before it is drawn. the simulator reproduces the sketch pixel for pixel before anything reaches the hardware. |
hardware
fob started life as a fire-boltt bsw051 smartwatch. the sensor board is gone; the firmware is replaced.
| part | detail |
|---|---|
| processor | realtek rtl8762d: arm cortex-m4f with hardware floating point, about 90 mhz, bluetooth 5 le |
| display | 368 × 448 amoled, 16-bit colour, driven over quad-spi with dma. black pixels are off pixels, so a dark interface is also the efficient one. |
| touch | hynitron chsc5816 capacitive controller on i2c, with an interrupt line |
| crown | rotary encoder (two phase lines) plus a push switch |
| haptics | eccentric-mass motor on a 25 khz pwm line, driven by a 1 khz pattern engine |
| power | single li-ion cell with charger; also boots from the charger alone |
| updates | flashed wirelessly from a laptop over bluetooth, with a watchdog and a boot back-off so a bad build can never lock out the next update |
field notes from bring-up
architecture
five layers, each only talking to the one beneath it. the same renderer and interface code also compile on a laptop, which is how every screen is checked before it is flashed.
renderer
the screen is drawn from a display list of vector primitives: rounded rectangles, rings, arcs, capsules, anti-aliased text and icons. only the rectangle that changed is redrawn, in twelve-line strips; while one strip is sent to the panel by dma, the next is already being drawn. the laptop simulator runs the same source and checks, for every screenshot, that the incremental result is identical to a full redraw.
who talks to whom
notifications, music and the time come from the iphone through bluetooth services built into ios, so the phone needs no app. updates, the claude helper and the pack studio live on a laptop. the nfc sticker on the back is passive: it simply hands a phone a link.
power states
a still image stays lit by the panel's own frame memory, so the ambient state needs no processor time between changes. the processor sleeps; the crown, the touch line and the radio wake it. battery figures will be measured on a fitted cell and published here.
interaction
the device is reached by feel, one-handed, often without looking. so the crown does the work and touch is a supporting actor.
| input | does | why |
|---|---|---|
| rotate | moves along the dial; inside a mode it is that mode's main control: volume, scroll, tempo, count | rotation needs intent, so a belt or bag cannot trigger it by accident. every notch is a haptic click. |
| press | enters a mode; inside a mode it performs the main action: play, pause, fire, flip | one action per mode keeps it learnable. |
| double-press | from anywhere: back to the dial. on the dial: back to carry | a universal way out. you can never be lost. |
| hold | screen off, and the same hold wakes it | it's the only gesture that works identically in every state. |
| press + rotate | a second action: seek in music, brightness elsewhere | doubles the control surface without adding a part. |
| touch | swipe left and right through a deck, tap on-screen buttons, drag lists. disabled in carry. | carry is where the device lives, brushing fabric and bags. touch has no job there, so it is off: no phantom input, and the touch controller can sleep. |
a single press waits about 0.2 s to be sure no second press follows. on-screen buttons that need to be instant (shutter, torch) use touch.
navigation
memory
every mode remembers its last position. carry resumes on the scene you last rested on, cards on the last card, music on its last page, inbox on its scroll position. double-press to the dial, switch modes, double-press again to carry: the device is exactly where you left it. the state lives in ram and is written to flash only after you stop moving for a moment, so the flash is never worn by scrolling.
torch
the whole screen turns white at full brightness. it switches itself off after two minutes. a swipe to the right opens its options: 2 minutes, 10 minutes, until i leave the mode, stay on. whatever the setting, it still switches off when the battery gets low.
haptic language
| pattern | feel | used for |
|---|---|---|
| tick | very short, light | each notch on the dial, list rows passing |
| tap / release | soft pair | crown down, crown up |
| click | crisp, dry | tally count, toggle |
| thud | heavy, short | coin landing, end of a list |
| count-down | three ticks, a pause, one long | camera timer |
| per-app | a short rhythm unique to each source | a notification: you can tell whatsapp from mail with your hip |
| alarm | long, repeating every 1.5 s | timer finished, claude needs you |
language
the interface follows the language of the author's own site: paper, ink and one quiet grey. one loud thing per screen, and it is type.
ink on black
the site is black on white by day and white on black by night. an amoled screen is always the night version: black is switched off, so the dark theme costs nothing. the white is warmed to bone, which is gentler to look at and matches the cream paper of the drawings it will sit next to.
type
| role | style | size on the 368 × 448 screen |
|---|---|---|
| giant | archivo 800, lowercase, tracking −4.5%, line height 0.78 | fit to the screen width (up to about 130 px) |
| display | archivo 800, lowercase | 40–60 px |
| title | archivo 800 | 22–34 px |
| body | archivo 400 | 14–17 px |
| label | archivo 400, lowercase, usually quiet grey | 11–12 px (never smaller) |
| numerals | tabular figures wherever digits change, so nothing shifts as they tick | — |
layout
20 px side margins (the panel's corners are rounded), an 8 px spacing unit, 1 px rules. every screen has the same chrome as the site's navigation: a top row of three cells, each a hairline over a small label (the time, where you are, status), and a matching caption row at the bottom. touch targets are at least 44 px.
signal colour
the interface has no accent. one signal colour is reserved for whatever is waiting on you: an incoming call, a claude prompt that needs an answer, an unread notification, a low battery. the signal is a single setting; six candidates, pick one to preview it across the page.
screens
every screen at the real panel ratio. several are live: they keep time, turn and scroll.
the dial
carry: the resting scenes
turn the crown to move between scenes. a few clock faces are shown; faces are small recipes, so there can be many.
cards
music, inbox, remote, claude
play and tools
motion
the details of motion and feedback follow the best touch interfaces: immediate response, springs, interruptible animation. the look comes from the author's site, not from anyone else's.
tokens
| token | curve | time | for |
|---|---|---|---|
| press | ease-out | 90 ms | pressed states, a button taking the finger |
| settle | cubic-bezier(0.2, 0.7, 0.2, 1) | 220–460 ms | things arriving: a screen, a toast, text fading in |
| leave | ease-in | 200 ms | things going away |
| dial | spring, stiffness 420, damping 34 | about 350 ms | notches of the dial, card swipes |
| sheet | spring, stiffness 260, damping 30 | about 450 ms | panels and options |
| breath | slow sine | 6–12 s | ambient scenes |
the website's page transitions also blur while they move. blurring is too expensive for a 90 mhz chip, so on the device the same feeling comes from fading and a few pixels of travel instead.
the curves, side by side
live: the dial and the boot sequence
boot: three thin rings draw clockwise, staggered. the hand-cut star settles in as they finish, the wordmark follows, then the screen hands over to carry.
storyboard: entering a mode
the giant word from the dial does not disappear; it shrinks and travels into the top label while the content rises underneath. the eye follows one thing.
frame budget
sixty frames a second leaves 16.7 ms. a full-screen redraw takes about 25 ms today, so full-screen motion currently runs near 40 fps. most motion moves small regions (a word, a bar, a card), which fit the budget. the animation engine redraws only what moved.
the pet
the one retro thing. a pixel creature at a desk, in a room with a window that follows the real time of day. it is also the device's mascot: it reacts to what the rest of the device is doing.
| when | the pet |
|---|---|
| idle | types, blinks, sips from the mug. steam rises. |
| a notification arrives | looks up, an alert mark in the signal colour pops over its head |
| music is playing | puts on headphones and bobs in time |
| claude is working | types faster, the screen fills with lines |
| night, or the screen dims | sleeps. the window shows the moon. |
sprite sheet
18 × 17 pixels, four tones plus the signal colour for the scarf. a whole scene costs a few hundred bytes of rectangles; the sprites are stored once.
packs
photos, faces and pets are not baked into the firmware. they are packs: small bundles of data swapped over bluetooth, the way a watch swaps faces.
| kind | contains | why it is small |
|---|---|---|
| assets | photos (dithered to a small palette), sprite sheets, qr codes, marquee text | stored in spare flash, outside the firmware |
| recipes | clock faces and ambient art, written as a short list of shapes tied to the time | the renderer already draws from shape lists, so a face is a few hundred bytes |
both kinds are pure data, never code, so a bad pack can't crash or brick the device. the studio is a small web page: it holds the library, previews each pack with the same renderer the device runs, converts photos and builds qr codes, then writes the chosen packs into the device's slots.
status
what runs today, what is designed and what is still to be proven.
running on the device
- vector renderer with dirty rectangles, strips and dma
- boot animation
- three clock faces
- touch, crown (software decoder) and button
- haptic pattern engine
- bluetooth with wireless updates
- clock sync and saved settings
- laptop simulator that checks every screen
designed, in this book
- the dial and nine modes
- per-mode memory
- carry scenes, cards, the pet
- torch with time limit and override
- pack format and the studio
- motion tokens
still to prove
- iphone notification and media services on this chip
- bluetooth hid camera shutter with ios
- asset storage in spare flash
- battery life on a fitted cell
- a motion sensor (none found yet)
order of work
| 1 | the shell: dial, carry, per-mode memory, new type and chrome |
| 2 | cards, with the pack pipeline for qr codes and photos |
| 3 | iphone services: notifications, music, time |
| 4 | the pet and the studio |
| 5 | sleep and power, measured on battery |