Pulsar
An eight-channel logic analyzer in a browser tab, over WebUSB.
Pulsar is the UI and the firmware for a logic analyzer, running in a browser tab. It sits where web technology meets bit-level work, and WebUSB is what joins the two: plug in a Cypress EZ-USB FX2LP, pick it out of the USB device list — yes, WebUSB lets you do that, and yes, only in Chrome — and you can capture and read any signal.
I used PulseView for this, the way the maker of the Chinese board I had suggested. It worked, and worked well. I still wanted the instrument in a browser tab, with an interface I liked, and with adding a decoder being easy.
The firmware ships with the app. Boards like this arrive empty — a bootloader and nothing else — and fx2lafw has to go in before the first capture. Pulsar notices and offers: eight kilobytes go into RAM over control transfers. Not to flash. Pull the cable and the device is blank again, and nothing that happened to it was permanent.
Then eight channels and nine presets, from 100 kHz to 24 MHz. At the top one the samples arrive at exactly the speed of USB 2.0: a bulk endpoint, 16 KB transfers, eight of them queued — and all of it has to be collected while the browser is drawing.
So none of it lives on the main thread. Samples go to a worker, into a ring buffer of chunks — up to 512 million samples — and the decoders run there too. A decoder never gets the whole capture: it reads through a window that streams it fixed-size slices, so its memory stays inside 64 KB whether the capture is a thousand samples or half a billion. The canvas gets no raw data either — it asks the worker for columns that are already reduced, two bytes to a pixel.
There are twenty-seven decoders: I²C, SPI, UART, CAN, LIN, JTAG, SWD, I2S, Modbus RTU, WS2812, 1-Wire, DHT11/22, MIDI, PS/2, Manchester, Wiegand, HD44780, quadrature, Step/Dir and on down the list. A new one is a file and a line in the barrel.
And one rule worth more than the rest: feeding a decoder a capture in slices has to produce exactly the annotations it produces in one call. Byte for byte. Every decoder has a test that checks it, and it always catches the same thing — a decoder that parked its cursor mid-frame and then, on the next slice, read its own edges as a fresh start.
Captures stay in the browser. A finished session goes into IndexedDB as the same .sr the export writes, along with its decoders, its channel layout and the zoom you left it at. Open it from the history and you are back where you were. The parsing happens on your machine; the project has no server.
PulseView doesn’t go anywhere either. Pulsar reads and writes ordinary sigrok .sr, compressed PulseView archives included, so a capture can start here and be finished there.
What it can’t do. WebUSB exists only in Chromium — Firefox and Safari don’t have it and aren’t planning to, so you can open a .sr there but not connect. Eight channels, a 24 MHz ceiling — that is what an FX2LP gives you. A fast bus is not something you look at with this, and that is fixed by a different analyzer, not by a different interface to this one.
Plain ES modules, not one runtime dependency, Vite and node --test. Nothing to install — it opens at a link.