To build one: a working board designed from this page is in
hardware/totem-v3.5-reference.
It has the reference board’s outline and its major parts where the photographs put them;
its passive values and traces are its own, and it uses parts in production where the
original’s are not: an ST LSM6DSV16X and LIS2MDL in place of the obsolete ICM-20948, among
others (its README, Parts changed). The file to hand to a fab and an assembler is
pcb/fab/totem-v3.5-assembly-package.zip, with
ASSEMBLY.md
inside: what to order, how to assemble, bring up and program the board.Bill of materials
Schematic
Net list
Every row’s pin comes from the firmware and is cited; the destination is what the photographs show at the other end.
The pull-ups named above are the ESP32’s internal ones, since that is what the firmware
asks for (
Pin.PULL_UP). Whether external pull-ups are also fitted — on I²C they normally
must be — is not visible.
Notes on the interesting nets
GPIO 4 is the power button and the power latch
While the Totem runs, GPIO 4 is an input with a pull-up and reads SW1. To switch off, the firmware re-opens the same pin as an output and drives it low, releasing an external hardware gate:Charging and regulation are separate parts
U3 is a charger only: a TP4056 takes VBUS from the USB-C receptacle and charges the cell, and that is all it does. It does not supply the board. The 3V3 the ESP32 runs on comes from U4, the SOT-23-5 sitting in its own group of capacitors, fed from the battery rather than from USB — which is why the Totem runs identically on and off the cable, and whyGPIO 34
reads the cell rather than the supply.
GPIO 39 is not wired to the TP4056’s CHRG pin, though that is the first guess and I
made it here before checking. Two facts rule it out:
modes.is_charging = self.v_in.value()(Power), so the pin reads high while charging.CHRGis open-drain and pulls low while charging. The polarity is backwards.- GPIO 34–39 on the ESP32 are input-only and have no internal pull resistors at all, and
Pin(39, Pin.IN)asks for none. An open-drain output with no pull-up would float whenever it was not charging, and the firmware would read noise.
v_in — input voltage. A divider from VBUS satisfies both
facts: high when the cable is in, pulled to ground by the lower resistor when it is out, and
the thing being sensed is the supply rather than the charger’s state.
The microphone is a loudness sensor
mic.read_u16 on GPIO 36 feeds Vibe Mode, which drives the halo from sound level
(new_vibe.dis:478). Nothing in the image decodes audio, and there is no I²S peripheral in
play: the MEMS part is sampled as an analogue level.
The GNSS link is binary, and the firmware configures it
The receiver is driven over UBX at 115200 withCFG-UART1OUTPROT-NMEA off and
CFG-MSGOUT-UBX_NAV_PVT_UART1 on, so it emits NAV-PVT every epoch and no $G… text at all
(Navigation). The Totem does not merely read its receiver, it tells
it what to be.
Both LED strips are one peripheral
Ring and crystal are separate data pins but the same driver, timing and wire order: WS2812 timings of 400/850/800/450 ns throughmachine.bitstream, three bytes per pixel, GRB,
no white channel (LEDs).
What is not known
These are gaps, not omissions, and each one names the photograph that would close it:
Flash with the halo switched off is what produced most of the markings above; the earlier set
had the board lit by its own LEDs, which erased them. It also took a grazing angle to read
U5’s laser marking at all: head-on, the lid reads as blank.
How this differs from the emulator board
The ESP32 emulator runs on a LILYGO T-Beam SUPREME — a different board with different parts:
The T-Beam SUPREME is sold with either a u-blox MAX-M10S or a Quectel L76K, so the emulator
asks its receiver at boot and logs the answer (
gnss receiver, and gnss= on the status
line). The bench board’s receiver was identified that way: its UBX-MON-VER reply reads MOD=MAX-M10S,
FWVER=SPG 5.10, and it rejects Quectel’s PCAS commands. Left unconfigured it solves from
GPS, Galileo, BeiDou and QZSS at once (its GSA sentences carry system IDs 1, 3, 4 and 5), with
GLONASS off.
Measured side by side on one desk, in the same minute: the Totem reported 18 satellites and
±2.2 m, the T-Beam 5–8 satellites and 3–13 m. The receiver is not the reason: it is the same
part. What is known to differ is what surrounds it. The Totem’s firmware configures its
receiver and the emulator sends nothing, and the bench T-Beam has no cell fitted, so its
receiver has no backup power and every power-up is a cold start. Which of these (or the antenna,
or how long each had been running) accounts for the gap has not been measured. Everything the
emulator derives from its own position — a peer’s bearing most of all — inherits the gap until
it is.