Search › A-Z › C › Calliope mini
Calliope mini
The Calliope mini v1, in the browser. A from-scratch Nordic nRF51822 (a 16 MHz ARM Cortex-M0) drives the real 5x5 LED matrix, the A and B buttons and the accelerometer, decoded from the on-chip peripherals exactly as on the hardware. It runs original bare-metal programs — a flashing heart, smiley buttons, dice-on-shake and a tilt dot — and the whole Cortex-M0 plugs into this site's shared debugger to single-step real Thumb instructions and read the live nRF51 memory map.
Honest scope: this runs genuine bare-metal programs, not the full MakeCode / MicroPython runtime, which needs interrupt and SoftDevice support the core does not yet have. The Calliope mini v1 has no on-board speaker, so it is naturally silent.
Visit the official Calliope mini site ↗
Runs on: Web browser
Calliope mini Online Emulator
Play Calliope mini using JavaScript directly in your browser.
Controls
Configurations
| Configuration | Emulator | Machine | OS | Legal | |
|---|---|---|---|---|---|
| Matrix Animation | Calliope mini | Calliope mini | open | Open ⛶ | |
| MicroPython: Flashing Heart | Calliope mini | Calliope mini | open | Open ⛶ | |
| RGB Colour Cycle | Calliope mini | Calliope mini | open | Open ⛶ | |
| Buzzer Melody | Calliope mini | Calliope mini | open | Open ⛶ | |
| Buttons | Calliope mini | Calliope mini | open | Open ⛶ |
Chips
Notes
Embedding
This is a two-layer stack: a real ARM CPU core underneath, and a from-scratch nRF51822 + Calliope mini board on top. It loads real Cortex-M0 flash images and runs them on the actual on-chip peripherals — original bare-metal programs that drive the LED matrix, the on-board WS2812 RGB LED and the on-board loudspeaker.
- The CPU.
cortex-m7.jsexecutes Thumb. The real chip is a Cortex-M0 (ARMv6-M); this core is ARMv7-M, a strict superset, so it runs the M0 image unchanged. It is byte-identical to the canonical copy used across the site's ARM emulators. - Real reset. The image is a real flash image with the ARM vector table at
0x00000000: on reset the board loadsSPfrom word 0 andPCfrom word 1, exactly like the silicon. - The board, in JavaScript.
calliope-board.jsmaps FLASH/RAM/APB/GPIO at their real nRF51 addresses, decodes the matrix GPIO into the 5x5 display, decodes the bit-banged WS2812 waveform on P0.18 into a live RGB value, feeds the buttons on their GPIO pins, answers the accelerometer's TWI reads, and turns the TIMER2/GPIOTE/PPI speaker path into audio.
| Piece | Kind | What it does |
|---|---|---|
Calliope.create(canvas) | factory | Build the ARM core + the nRF51 memory map + peripherals. |
load(bytes) / reset() | method | Copy the flat image into FLASH; reset loads SP/PC from the vector table. |
runFrame() / genAudioFrame() | method | Step ~120k instructions (the LED scan is integrated over the frame) and produce one video-frame of speaker audio. |
setButton(id,down) / setTilt(x,y) / shake() | input | Drive the button GPIO levels and the accelerometer X/Y/Z. |
present() | method | Draw the 5x5 red-LED display, the RGB LED and the speaker indicator. |
Debugger integration
calliope-debug.js reads window.EMU_BOOT and hands the shared debugger a genuine ARM Cortex-M0 machine — the same core the program runs on, exposed instruction-accurately.
- Registers.
registers()reads r0-r12, SP, LR, PC, xPSR and the APSR flags N/Z/C/V live each refresh; each has aset()that writes straight back into the core's register file. - Disassembly. FLASH is decoded with the shared
cortex-m7decoder (the Thumb-2 disassembler; ARMv6-M is a subset), so the code window shows real ARM mnemonics at the real reset address0x00000000. - Single-step. Step calls
transport.stepInsn, which advances the core exactly one Thumb instruction. PC and the registers update after each step. - Breakpoints & watchpoints. Execution breakpoints are a PC set the run-loop checks before each instruction; write watchpoints wrap the board's memory-write path and pause when a watched address is written. Both are real.
- Memory map. Four chips read the real address space side-effect-free: FLASH (program, disassembled), RAM (0x20000000), the GPIO port (0x50000000 — watch OUT/DIR/IN change as the matrix scans and the RGB line bit-bangs), and the APB peripheral block (0x40000000 — CLOCK, TWI0, TIMER0/1/2, GPIOTE, PPI, RNG).
Architecture
The Calliope mini is a German educational board — a close cousin of the BBC micro:bit v1 — built on the same Nordic nRF51822: a 16 MHz ARM Cortex-M0 with 256 KB flash and 16 KB RAM. On board: a 5x5 red LED matrix, two buttons (A and B), an on-board WS2812 RGB LED, an on-board loudspeaker (via the motor H-bridge), and a BMX055 accelerometer + compass on I2C. The board wiring below is verified against the Calliope mbed target PinNames.h and the calliope-mini/microbit-dal fork.
- The 5x5 display is a 3x9 multiplexed matrix — wired IDENTICALLY to the micro:bit v1 (MICROBIT_SB2). Rows ROW1..ROW3 =
P0.13/14/15(source, HIGH); columns COL1..COL9 =P0.04..P0.12(sink, LOW); the same (col,row)→(x,y) map. The board integrates the scan over each frame into the logical 25-LED image. - Buttons A =
P0.17, B =P0.16, active-low with a pull-up. (Button B differs from the micro:bit'sP0.26.) - On-board RGB LED (WS2812B) on
P0.18. The program bit-bangs the one-wire 800 kHz waveform; the board measures the HIGH-pulse width (in executed instructions) to recover each bit and latches a 24-bit GRB colour on the long reset gap — the genuine WS2812 line protocol, decoded into one live RGB value. - On-board loudspeaker on the motor H-bridge (
P0.29). The Calliope makes SOUND (unlike the micro:bit v1). A tone is generated the real nRF51 way: TIMER2 counts to its compare value (with the COMPARE0→CLEAR short for auto-reload), each compare event toggles the speaker pin through a GPIOTE task, wired by a PPI channel — so the pin emits a square wave at the note frequency. The board recoversfreq = timer_clock / (2 × CC0)from the emulated registers and synthesises that square wave to the shared audio sink. See the Sound notes. - Accelerometer/compass — a BMX055 at I2C address
0x18on TWI0 (SCLP0.19, SDAP0.20). It is high-level-emulated: real nRF51 TWI transactions return CHIPID0xFAand the settable X/Y/Z from the on-screen tilt / shake controls. - Timing/entropy. CLOCK, the TIMERs and RTCs, GPIOTE, PPI, and the RNG are implemented; the radio is present but stubbed (no real RF).
- Content. Four original CC0 bare-metal programs (matrix animation, RGB colour cycle, buzzer melody, buttons), compiled with clang for thumbv6m. No proprietary firmware is used.
Sound
Pattern S (authored synthesis) driven by the real nRF51 tone path. The Calliope mini's on-board loudspeaker sits on the motor H-bridge output P0.29. The nRF51822 has no dedicated PWM peripheral, so — exactly like the Calliope's own CalliopeSoundMotor driver — a tone is generated with TIMER2 + GPIOTE + PPI: TIMER2 runs at 1 MHz (PRESCALER 4) with a COMPARE0→CLEAR short so it auto-reloads every CC0 ticks; a GPIOTE channel is configured as a Task/Toggle on the speaker pin; and a PPI channel wires TIMER2's EVENTS_COMPARE[0] to the GPIOTE TASKS_OUT. The pin therefore toggles once per CC0 period, emitting a square wave.
The board's speakerFreq() follows that exact chain: it finds an enabled PPI channel whose TEP is a GPIOTE toggle-task on the speaker pin and whose EEP is a running TIMER2 compare event, then recovers freq = (16 MHz>>PRESCALER) / (2 × CC0). Each video frame genAudioFrame() renders that square wave with a persistent phase accumulator (so notes don't click), duplicated to L+R, at exactly Math.round(EmuAudio.sampleRate/60) interleaved-stereo Int16 samples, and pushAudio() pushes it to the shared EmuAudio sink. The pitch is correct because the frequency comes straight from the emulated CC0, not a fixed table.
The transport exposes the standard mute contract — setMute/isMuted delegate to EmuAudio — and it starts muted (browsers block audio before a gesture); the shell's Sound button unmutes from a real click. The "Buzzer Melody" program plays a recognisable tune so unmuting is immediately audible.