Using Text to Chip

Text to Chip is a browser IDE where you write small BASIC MISSION programs (Sakura BASIC). The browser compiles them to a flat list of bytecode instructions; a tiny tick-based virtual machine runs that bytecode — either in the in-browser simulator or on a real microcontroller over Web Serial. The same bytecode runs in both places.

Browser requirement for real hardware: Web Serial works only in a Chromium desktop browser (Chrome, Edge, Brave) over HTTPS — which https://textochip.com provides. Firefox/Safari and mobile can still use the Simulator.

Where your program runs

Simulator
No hardware

Runs entirely in the browser. Works for everyone, any OS. Best place to start.

ESP32-S3
Verified hardware

The reference board. Flash the Zephyr firmware once, then upload & run over USB.

More boards
One toolchain

The firmware is Zephyr, so the same code targets new chips — only a tiny HAL file changes. Nordic nRF54L next.

The workflow (same for every backend)

  1. Describe what you want in the ribbon's input, or pick a ready program from the header's Examples / Missions menus. The program takes shape as a block in the ribbon.
  2. Choose where it runs with the Simulator / Real board toggle.
  3. Compile — the console shows the result (instruction count and any warnings).
  4. Upload & Run — sends the program and starts the VM (with Auto-run on, this happens after every change).
  5. Stop halts it; type an OVERRIDE: command in the same input (e.g. OVERRIDE: STOP or OVERRIDE: SET 4 0) to inject one instruction live, without re-uploading.

1 · Simulator (no hardware)

  1. Open https://textochip.com in any browser.
  2. Leave the toggle on Simulator (it auto-connects).
  3. Click Upload & Run. The on-screen LEDs, buzzer indicator and button mirror exactly what a real board would do.
  4. For programs that read the button, click the on-screen button to drive the input pin.

The simulator is a TypeScript VM with the same instruction set and tick model as the firmware, so a program that works here behaves identically on the board.

The ribbon — describe it in plain words

The left column is a single ribbon where the conversation and the program live together. Type what you want in plain language in the input at the bottom — the assistant writes Sakura BASIC for you and it appears right there as a program block, with a short reply above it. No separate editor to manage (though you can open the full .bas any time with show full .bas).

Keep chatting to refine it: “make it faster”, “add a beep”, “use yellow instead” — each new version appears in the ribbon with the changed parts highlighted, and the browser compiler checks it automatically. From the same input you can also type a numbered BASIC line to edit the program directly, or an OVERRIDE: command to act on the running board.

The explanation and the reply come back in the site language — switch it with the language icon (the flag) in the header.

Auto-run

There's an Auto-run toggle below the ribbon, on by default. When the program changes and compiles cleanly, it's loaded and run automatically on the active backend — so you see the result live without clicking Upload & Run yourself.

Missions you can tune

A mission packs a whole behavior into one line. MISSION "SEMAFORO" runs a complete pedestrian-crossing traffic light — the full light cycle, the walk beep on red, and a real crossing button — from a single statement. A second mission, MISSION "PIANOLA", turns the same board into a playable one-button keyboard (each note sounds on the buzzer and lights an LED).

It's parameterizable. Add a WITH clause to adjust the timings, the beep and the button:

MISSION "SEMAFORO" WITH green=6s yellow=1s red=4s beep=off|slow|fast button=on|off minGreen=2s

Ranges: green 2–15s, yellow 0.5–3s, red 2–15s, minGreen 2–10s. beep is off, slow or fast; button is on or off. Durations accept decimals or milliseconds (0.5s, 1500ms). Set just the parameters you care about, e.g. MISSION "SEMAFORO" WITH green=4s beep=fast.

The pedestrian button

When button=on, pressing the button is a crossing request: the green LED blinks immediately to acknowledge it, then the light turns to red as soon as green has lasted at least minGreen (so a press can't stop traffic instantly). On the simulator, click the on-screen button; on hardware, wire it to GPIO 6 (active-low, to GND).

Fixed safety guardrails

Some things can't change — they're safety guardrails: the lights always cycle green → yellow → red, one light at a time, the walk beep sounds only on red, and a button press can never cut green below minGreen.

2 · ESP32-S3 (recommended, verified)

Reference board: Freenove ESP32-S3-WROOM (USB-C, two USB ports). You flash the generic Zephyr VM firmware once; after that you upload bytecode from the IDE as many times as you like — no re-flashing to change the program.

Get the firmware

The board runs a small generic VM firmware built with Zephyr. You build and flash it once from the repo's firmware-zephyr/ folder, then upload programs from the browser. The full, copy-pasteable steps live in firmware-zephyr/README.md.

What you need

Wiring

ComponentPinWiring
Green LEDGPIO 1→ resistor → GND
Yellow LEDGPIO 2→ resistor → GND
Red LEDGPIO 4→ resistor → GND
Buzzer (passive)GPIO 5→ GND
Button AGPIO 6→ GND (internal pull-up; active-low)

These pins come from the board profile (lib/boardProfile.ts); the compiler bakes them into the bytecode. GPIO 1/2/4/5/6 are safe digital I/O on the ESP32-S3.

Build & flash the firmware (one time)

  1. Set up the Zephyr toolchain — a west workspace and the Zephyr SDK (Zephyr's Getting Started guide). The firmware sources are in firmware-zephyr/.
  2. From firmware-zephyr/, build for the ESP32-S3:
    west build -b esp32s3_devkitc/esp32s3/procpu zephyr
    Run west packages pip --install once so esptool ≥ 5.0.2 is on your PATH at flash time.
  3. Plug in the board's “USB UART” port (the CH343 chip) and flash with west flash — esptool's auto-reset into download mode works on this port.
  4. If a flash can't auto-reset (e.g. the firmware is already running): hold BOOT, tap RST, release BOOT, then west flash again.
  5. Two ports, two jobs: you flash over the “USB UART” port, but you connect the IDE over the “USB OTG” (native-USB) port — do not swap them.

Connect & run from the IDE

  1. Open https://textochip.com in Chrome/Edge/Brave.
  2. Switch the toggle to Real board.
  3. Click Connect board and pick the board's “USB OTG” (native-USB) port — it shows as CDC_ACM_serial_backend. (Not the “USB UART” port you flashed from.)
  4. Click Upload & Run. Use Stop and Override at runtime.
Pick the right port. The IDE connects over the “USB OTG” native-USB port — an app-provided CDC-ACM that does not reset on connect. The “USB UART” port is only for west flash; opening it in the browser would reset the chip (you'd see WARN: no PONG).

3 · Other boards (Zephyr)

Because the firmware is Zephyr, the very same VM, ISA and missions run on any board Zephyr supports — only a tiny HAL file changes. The browser compiler, the serial protocol and your .bas programs stay identical, so the whole IDE flow is unchanged from board to board.

What changes per board

Two things only: the GPIO numbers in lib/boardProfile.ts (the compiler bakes them into the bytecode), and one HAL implementation — about 9 functions mapping pins/PWM/clock to that chip. Then build for the target with west build -b <board> zephyr.

Nordic nRF54L (incoming)

The next target is the nRF54LM20 DK. Build it with the nRF Connect SDK (Nordic's Zephyr): west build -b nrf54lm20dk/nrf54lm20a/cpuapp zephyr, then west flash. Same IDE flow over Web Serial; BLE OVERRIDE and edge-AI missions on the Axon NPU come next.

The language, briefly

A first program — a looping traffic light (Project 01):

10 LED red, on
20 WAIT 5s
30 LED red, off
40 LED yellow, on
50 WAIT 1s
60 LED yellow, off
70 LED green, on
80 WAIT 5s
90 LED green, off
100 GOTO 10

The executable subset compiles to bytecode: LED, WAIT, GOTO, GOSUB/RETURN, IF … THEN, LET, arithmetic and comparisons, SOUND/PLAY (beeps & melodies), BUTTON("A"), and MISSION "SEMAFORO" (a complete pedestrian crossing). Statements that need absent hardware (motors, camera, GPS…) still compile — they emit a no-op and a console warning instead of failing.

Troubleshooting