简体中文 | English
A web-based console for the tinySA signal generator mode. Pure frontend, no backend — connects to the device over the Web Serial API and supports every tinySA generation.
Hardware setup — tinySA Ultra+ ZS407 driven by tinysa-webgen, verified on a harogic SAN-90:
- Full device support — Basic / Ultra ZS405 / ZS406 / ZS407, capability-driven UI, model auto-detected
(parsed from
info; firmware ≥v1.4 dropped the ZS tag fromversion). - Signal generator control — inline freq/level input, CW & freq/level sweep, AM/FM/NFM/WFM modulation, RF on/off, spur/ext_gain/output mode, and a level-limit engine that clamps before the device silently reduces the level (hardware-calibrated).
- Sweep/modulation exclusivity — sweeps armed with
sweep go, modulation is CW-only (hardware-verified:waitcan deadlock the firmware CLI with modulation active). - Presets & history — deduplicated transmit history with CW/MO/SW badges, one-click recall; auto-transmit defaults OFF after connecting.
- Debug panel — raw tx/rx logging with regex filter, command autocomplete + mini console.
- Safe by design — connecting only reads device state; never transmits unless you press Transmit.
- i18n & themes — English / 简体中文, fluorescent-green dark/light themes, persisted.
- Virtual device — built-in simulator to try the UI without hardware (dev builds).
- Pure frontend — Web Serial direct connection, no backend, responsive & touch-friendly.
- Browser: Chrome / Edge / Opera, or Firefox 151+ (Web Serial API; localhost or HTTPS).
- Node.js ≥ 18 for building.
Left: the tinysa-webgen console driving the tinySA signal generator. Right: the
corresponding signal as measured on a harogic SAN-90 spectrum analyzer
(file names ending in _harogic_result). Click an image to view it full size.
| Web console | SAN-90 spectrum analyzer result |
|---|---|
![]() |
![]() |
| 1 GHz CW tone | carrier @ 1 GHz |
![]() |
![]() |
| FM 400 MHz (1 kHz mod, 30 kHz dev) | FM spectrum spread |
![]() |
![]() |
| Frequency sweep (center 1090 MHz, span 600 MHz) | sweep output on SAN-90 |
10 MHz CW — harmonics & phase noise, measured on the SAN-90:
| Web console | SAN-90: harmonics | SAN-90: phase noise |
|---|---|---|
![]() |
![]() |
![]() |
| 10 MHz CW | H1–H5 harmonics | phase noise |
npm install
npm run dev # dev server (http://localhost:5173)or build and serve:
npm run build # outputs dist/
npx vite preview # http://localhost:4173If you have make installed, the same commands are available as:
make install # npm install
make dev # dev server (http://localhost:5173)
make build # outputs dist/
make run # build + preview (http://localhost:4173)
make test # run the unit testsOpen the page → click Connect Device → pick your tinySA's serial port in the browser dialog, or click Virtual Device to try the simulator. After connecting, select Low Output (and High Output on the Basic) to enter the signal generator.
npm test # vitest — parsers, capability/level model, framing, simulator, device layer, hw fixtures
python3 tests/hw/run_hw_tests.py # hardware integration (tinySA + SAN-90; report: docs/zh/hwtest-report.md)src/
├─ core/ i18n (en/zh), theme (dark/light), store
├─ serial/ WebSerial transport (ch> prompt framing, queue, resync, retry) + simulator
├─ protocol/ number/response parsing, device identification, capability & level-limit model
├─ device/ TinySADevice state machine + typed actions + reconcile polling
└─ ui/ DOM app (panels, modals, keyboard/long-press input, rendering)
docs/
├─ en/ English requirements & design notes (analysis.md, spec.md, context.md, requirements.md)
├─ zh/ 中文需求与设计文档(analysis.md, spec.md, context.md, requirements.md)
└─ ref/ original reference files (tingSA_USB_interface.pdf, tracking_generator.py)
- USB CDC, 115200 8N1 (baud is cosmetic over USB CDC); commands end with
\r, responses framed on thech>prompt; the echoed command line is stripped. - Device identification:
version+info(tinySA ULTRA+ ZS407first line),hopprobe (Ultra only),level ?(reveals generator mode + range, but the firmware prints hard-coded Basic ranges even on the Ultra — the capability table wins). - Level limit: firmware
set_output_pathformulamaxLevel(f) = level_max − correction(f) − AMreserve; thelevelcommand clamps to the nominal range first, and the Ultra square/mixer bands (>1.13 GHz) deliver far less than nominal — the frontend applies empirical band caps. - CW stepping: enter generator mode with
sweeptime 0.003(M_GENLOW forces 2 s by default) →sweep cw <f>→wait→resume. - Sweep:
sweep <start> <stop> <points>→sweep go(firmware__SWEEP_RESTART__: an unarmed range sweep aborts after the first point in output mode) →resume; stop withpause+sweep abort. - Modulation/sweep exclusivity: with modulation active the sweep thread runs ~25 s per cycle
(128 modulation steps × 450 points);
waitthen blocks the shell thread (the USB reader) and wedges the host — modulation is CW-only, any sweep op first sendsmodulation off.
UI font: LXGW WenKai (SIL Open Font License), bundled as woff2.
MIT (code). LXGW WenKai font: SIL OFL 1.1.
This project is not a derivative of the tinySA firmware (GPL-3.0): it contains no firmware code and only talks to the device over the serial protocol. tinySA itself is a project of Erik Kaashoek — see https://tinysa.org and https://github.com/erikkaashoek/tinySA. "tinySA" is used for interoperability only.









