Z80 LED Chaser in C (no board) is a runnable microcontroller simulation example on SensBench — open the wired circuit, inspect the code, and compile real firmware in your browser, no install needed. Last updated Aug 14, 2026.

FREE SIMULATOR EXAMPLE · ADVANCED

Z80 LED Chaser in C (no board)

This example runs an LED chaser written in C on a programmable Z80 — compiled by SDCC to Z80 machine code and executed on the chip. It proves the Z80 is programmable in C, not just assembly, with the real cross-compile toolchain behind the Run button.

Board Programmable Z80 chip (Zilog Z80, standalone — no Arduino)
Difficulty advanced
Category circuits
Libraries None — just the Arduino core
Runs in Sensbench browser simulator — free, no account
Programmable Z80 chip running an LED chaser written in C and compiled by SDCC in the Sensbench simulator

The exact circuit you get when you open this example — already wired, ready to run.

The sketch

* LED chaser written in C, compiled to Z80 by SDCC.
 *
 * Demonstrates that you can program the Z80 chip in C (not just asm).
 * The backend runs:
 *     sdcc -mz80 --data-loc 0x8000 program.c
 * and feeds the resulting Intel HEX into the chip via vx_rom_read.
 *
 * The MMIO addresses (0xC000 LED, 0xC003 BTN, 0xC001 UART_DATA,
 * 0xC002 UART_STAT) match the z80-cpu chip's memory map.
 *
 * Behaviour: walks a single LED back and forth across the 8 outputs
 * (true Larson scanner, with direction reversal).
 */
#define LED_OUT   (*(volatile unsigned char *)0xC000)
#define BTN_IN    (*(volatile unsigned char *)0xC003)

static void delay(unsigned int loops) {
    while (loops--) {
        __asm
        nop
        nop
        nop
        nop
        __endasm;
    }
}

void main(void) {
    unsigned char bit = 0x01;
    /* MUST be signed: SDCC treats plain `char` as unsigned on Z80, so
       dir=-1 would read back as 255, the "walk right" branch would never
       run, and the bit would just shift left off the end and stay dark. */
    signed char dir = 1;   /* +1 = walking left, -1 = walking right */
    while (1) {
        LED_OUT = bit;
        delay(5000);

        if (dir > 0) {
            bit <<= 1;
            if (bit == 0x80) dir = -1;
        } else {
            bit >>= 1;
            if (bit == 0x01) dir = 1;
        }
    }
}

How it works

The program is written in C (chaser.c) and compiled to Z80 machine code by SDCC, then loaded into the chip’s ROM space. The chaser walks a single LED back and forth using memory-mapped IO — writing to address 0xC000 drives the LED port, reading 0xC003 polls the button.

The backend pipeline — SDCC compile, Intel HEX generation, ROM load — is the real toolchain of Z80 development, compressed into the simulator’s run cycle. The C source is editable in the chip’s editor, so the edit-compile-run loop is the same one a 1980s developer used, minus the floppy disks.

Before you build it for real

The MMIO addresses are fixed hardware: write to the wrong address and the program corrupts its own RAM or jumps into data — there is no memory protection on a Z80. The C code is small but the compiler output is not: SDCC’s Z80 code is larger than hand assembly, so the comfortable RAM budget of the demo would tighten fast in a real product. And the –data-loc 0x8000 flag matters: Z80 address space is segmented by design, and the wrong data segment puts globals where the stack expects to live.

Related examples

FAQ

Can you really compile C for a Z80?

Yes — SDCC (sdcc -mz80 --data-loc 0x8000 program.c) compiles C to Z80 machine code. The example exists to prove it: the same chaser logic that assembly would hand-write, expressed in C and cross-compiled. The MMIO addresses (0xC000 LED, 0xC003 BTN, UART at 0xC001/0xC002) are the chip’s port map.

Why would anyone choose C over assembly on a Z80?

Readability and portability. The compiled output is larger and slower than hand assembly, but the source is maintainable and the same logic ports to other targets. For a chaser demo the trade is invisible; for a 1 KB ROM game, assembly still wins.