Skip to main content
Every other page here was derived from the firmware image. This one starts at the other end: a Totem v3.5 opened up and photographed, then matched against the pins the firmware actually drives. Each net below has a part at one end and a cited line of bytecode at the other.
This is a net-level schematic, not a reverse-engineered one. It says which parts exist and what each MCU pin is connected to. It does not give passive values, series resistors, divider ratios or trace routing: those live under the components and on inner layers, and no photograph of an assembled board can recover them. Nothing here is guessed to fill a gap — where the answer is not known, the page says so.
Confidence markers mean what they do elsewhere in these docs. Confirmed additionally means a part number legible on the silkscreen, or a count taken from the photograph and matched independently in the bytecode. Inferred means the photograph is consistent and nothing contradicts it.
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:
That is the real “off” (Power). Button and latch share one net, so the board cannot read the button while it is asserting the latch — which is exactly what powering down means.

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 why GPIO 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. CHRG is 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.
The firmware’s own name for it is 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 receiver is driven over UBX at 115200 with CFG-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 through machine.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.