fob

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.

not a watch.
sketched on paper first,then drawn in pixels.
368 × 448amoled panel, 16-bit colour
crown + touchone switch, one dial, one panel
bluetooth leupdates, phone services, a laptop helper
from scratchrenderer, interface, motion, haptics, firmware
01the idea

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.

it hangs outsideclipped to a belt loop or a bag, threaded on keys. it is visible all day, so it has to look good when nobody is touching it.
it rests, it doesn't waitthe home state is an ambient scene (a photo, a pet, a globe, a clock) rather than a grid of apps.
it has modes, not appsnine modes on a dial. each one does one thing well and remembers where you left it.
it borrows nothingeverything on screen is drawn by firmware written for this device. no vendor interface survives.
02principles

principles

principlewhat it means on the device
one switchthe crown is the only button. rotate, press, press twice, hold. the whole vocabulary fits in one minute and works without looking.
ambient firstthe device spends nearly all of its life at rest on a belt. the resting state is designed before any mode.
quiet by defaultthe 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.
continuityevery mode remembers its last page. double-press returns to the dial; the next press returns to exactly where you were.
nothing inventedevery value shown is read from a real source. if a source is unavailable, that piece is left out rather than faked.
motion is the productsprings, interruptible gestures, haptics landing on the same frame as the visual settle. a small interface that feels expensive.
paper firstevery screen is sketched by hand before it is drawn. the simulator reproduces the sketch pixel for pixel before anything reaches the hardware.
03hardware

hardware

fob started life as a fire-boltt bsw051 smartwatch. the sensor board is gone; the firmware is replaced.

partdetail
processorrealtek rtl8762d: arm cortex-m4f with hardware floating point, about 90 mhz, bluetooth 5 le
display368 × 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.
touchhynitron chsc5816 capacitive controller on i2c, with an interrupt line
crownrotary encoder (two phase lines) plus a push switch
hapticseccentric-mass motor on a 25 khz pwm line, driven by a 1 khz pattern engine
powersingle li-ion cell with charger; also boots from the charger alone
updatesflashed 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

half the wires were floatingearly builds drove two of the panel's four data lines. every pixel was half wrong: greys came out green, edges came out blue. connecting the other two fixed all colour in one change.
a rail that resets the chipthe oled's high-voltage supply must be soft-started with a pwm ramp. switching it on hard resets the processor; on a weak charger even the ramp needs slow steps.
a crown that never countedthe chip's hardware decoder reads nothing on this board, so the crown is decoded in software on a 1 khz timer. it now counts both directions.
95 ms to 25 msa full-screen redraw first took 95 ms. hot loops moved into ram, the fpu's square root and flat spans for solid shapes brought it to about 25 ms.
04architecture

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.

05interaction

interaction

the device is reached by feel, one-handed, often without looking. so the crown does the work and touch is a supporting actor.

inputdoeswhy
rotatemoves along the dial; inside a mode it is that mode's main control: volume, scroll, tempo, countrotation needs intent, so a belt or bag cannot trigger it by accident. every notch is a haptic click.
pressenters a mode; inside a mode it performs the main action: play, pause, fire, flipone action per mode keeps it learnable.
double-pressfrom anywhere: back to the dial. on the dial: back to carrya universal way out. you can never be lost.
holdscreen off, and the same hold wakes itit's the only gesture that works identically in every state.
press + rotatea second action: seek in music, brightness elsewheredoubles the control surface without adding a part.
touchswipe 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

patternfeelused for
tickvery short, lighteach notch on the dial, list rows passing
tap / releasesoft paircrown down, crown up
clickcrisp, drytally count, toggle
thudheavy, shortcoin landing, end of a list
count-downthree ticks, a pause, one longcamera timer
per-appa short rhythm unique to each sourcea notification: you can tell whatsapp from mail with your hip
alarmlong, repeating every 1.5 stimer finished, claude needs you
06design language

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.

giant lowercasearchivo extrabold, tracked tight, set to fit the width of the screen. the one loud thing. sometimes it is cropped by the edge on purpose.
hairlines, not boxesone-pixel rules above small lowercase labels. structure comes from lines and space; blocks have square corners.
colour lives in contentphotographs, hand-drawn art and pixel art carry colour. the interface around them is monochrome.
the staran irregular, hand-cut star is the mark: a flat paper shape, drawn imperfectly, white on black.

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

carry
rolestylesize on the 368 × 448 screen
giantarchivo 800, lowercase, tracking −4.5%, line height 0.78fit to the screen width (up to about 130 px)
displayarchivo 800, lowercase40–60 px
titlearchivo 80022–34 px
bodyarchivo 40014–17 px
labelarchivo 400, lowercase, usually quiet grey11–12 px (never smaller)
numeralstabular 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.

07screens

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

08motion

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.

respond in the same framea crown notch or a touch moves something on screen and clicks the motor in the same frame. nothing waits for an animation to finish.
everything is interruptiblegrab an animation mid-flight and it carries on from its current position and speed. a flick keeps its momentum.
springs follow fingersthings that track the crown or a finger use springs; things that simply appear use a long settling curve.
ambient motion is slowcarry scenes move over six to twelve seconds and stay low-contrast. it should read as alive, never as busy.

tokens

tokencurvetimefor
pressease-out90 mspressed states, a button taking the finger
settlecubic-bezier(0.2, 0.7, 0.2, 1)220–460 msthings arriving: a screen, a toast, text fading in
leaveease-in200 msthings going away
dialspring, stiffness 420, damping 34about 350 msnotches of the dial, card swipes
sheetspring, stiffness 260, damping 30about 450 mspanels and options
breathslow sine6–12 sambient 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

linear
ease in-out
settle
spring

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.

09the pet

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.

whenthe pet
idletypes, blinks, sips from the mug. steam rises.
a notification arriveslooks up, an alert mark in the signal colour pops over its head
music is playingputs on headphones and bobs in time
claude is workingtypes faster, the screen fills with lines
night, or the screen dimssleeps. 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.

10packs

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.

kindcontainswhy it is small
assetsphotos (dithered to a small palette), sprite sheets, qr codes, marquee textstored in spare flash, outside the firmware
recipesclock faces and ambient art, written as a short list of shapes tied to the timethe 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.

11status

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

1the shell: dial, carry, per-mode memory, new type and chrome
2cards, with the pack pipeline for qr codes and photos
3iphone services: notifications, music, time
4the pet and the studio
5sleep and power, measured on battery