Skip to content

mahdi-salmanzade/glyph-cli

Repository files navigation

glyph-cli

Control 137 LEDs directly from your terminal. No SDK. No app sandbox. Pure sysfs.


Nothing Glyph LED Matrix



v1.0.0  ·  Nothing Phone (4a) Pro  ·  Magisk Module  ·  Shell + Web



What is this

GlyphCLI is a Magisk module that gives you raw, unrestricted control over the 137-LED matrix on the Nothing Phone (4a) Pro. It bypasses the Ketchum SDK entirely, writing directly to the AW20144 sysfs interface. Includes 30+ commands, a web control panel, a background daemon, audio visualizer, games, and text rendering on a 13x13 circular grid.


Hardware

Component Details
LED Controller AW20144 (LITEON)
Bus I2C-0, address 0x0020
Chip ID 0x74, Hardware T0
Physical LEDs 137 (circular mask of 13x13 grid)
Brightness 12-bit PWM per LED (0-4095), 8-bit global (0-255)
Red Indicator Separate PMIC LED at /sys/class/leds/red
sysfs Path /sys/class/leds/matrix-leds/
Target Device Nothing Phone (4a) Pro — A069P / FroggerPro

The 13x13 logical grid has 169 cells, but only 137 are physically wired. The circular mask cuts the corners:

Row  0:  5 LEDs   cols 4-8       ·  ·  ·  ·  o  o  o  o  o  ·  ·  ·  ·
Row  1:  9 LEDs   cols 2-10      ·  ·  o  o  o  o  o  o  o  o  o  ·  ·
Row  2: 11 LEDs   cols 1-11      ·  o  o  o  o  o  o  o  o  o  o  o  ·
Row  3: 11 LEDs   cols 1-11      ·  o  o  o  o  o  o  o  o  o  o  o  ·
Row  4: 13 LEDs   cols 0-12      o  o  o  o  o  o  o  o  o  o  o  o  o
Row  5: 13 LEDs   cols 0-12      o  o  o  o  o  o  o  o  o  o  o  o  o
Row  6: 13 LEDs   cols 0-12      o  o  o  o  o  o  o  o  o  o  o  o  o
Row  7: 13 LEDs   cols 0-12      o  o  o  o  o  o  o  o  o  o  o  o  o
Row  8: 13 LEDs   cols 0-12      o  o  o  o  o  o  o  o  o  o  o  o  o
Row  9: 11 LEDs   cols 1-11      ·  o  o  o  o  o  o  o  o  o  o  o  ·
Row 10: 11 LEDs   cols 1-11      ·  o  o  o  o  o  o  o  o  o  o  o  ·
Row 11:  9 LEDs   cols 2-10      ·  ·  o  o  o  o  o  o  o  o  o  ·  ·
Row 12:  5 LEDs   cols 4-8       ·  ·  ·  ·  o  o  o  o  o  ·  ·  ·  ·
                                 5 + 9 + 11 + 11 + 13×5 + 11 + 11 + 9 + 5 = 137

Physical LED indices run sequentially left-to-right, top-to-bottom: row 0 is indices 0-4, row 1 is 5-13, and so on through row 12 at 132-136. See the full coordinate map in glyph-svg/nothing-glyph-map.json.


Install

Flash through Magisk Manager:

GlyphCLI-v1.0.0.zip

Or via adb:

adb push GlyphCLI-v1.0.0.zip /data/local/tmp/
adb shell su -c magisk --install-module /data/local/tmp/GlyphCLI-v1.0.0.zip

No reboot required. All commands require root (su).


Commands

Basic Control

Fill
Command Description
glyph on [brightness] Turn on all LEDs (global 0-255, default 255)
glyph off Turn off everything
glyph brightness [0-255] Get or set global brightness

LED Control

Gradient
Command Description
glyph set <idx> <0-4095> Set single LED by physical index (0-136)
glyph fill [brightness] Fill all 137 LEDs at one brightness
glyph level <n> [bright] Light the first N LEDs
glyph range <start> <end> [bright] Light a contiguous range
glyph frame <values|@file> Write raw 137-value frame

Red Indicator LED

Red LED
Command Description
glyph red on [0-255] Solid red LED
glyph red blink [bright] [on_ms off_ms] Hardware-timed blink via kernel timer trigger
glyph red off Red LED off

The red indicator LED is on a separate PMIC controller, independent of the 137-LED Glyph matrix.

Text & Display

Print HI
Command Description
glyph print <text> [speed] [bright] Scrolling marquee across the grid
glyph number <num> [brightness] Display a centered number
glyph clock [brightness] Live digital clock (HH:MM)
glyph clock --analog Analog clock with hour markers and hands
glyph countdown <secs> [bright] Countdown timer with blink at zero

Uses a 5x7 bitmap font rendered onto rows 3-9 of the grid.

Patterns

Alternate
Command Description
glyph alternate [step] [bright] Every Nth LED
glyph gradient [max] Smooth brightness ramp 0 to max
glyph progress <0-100> [bright] Progress bar (percentage of 137 LEDs)

Animations

Wave

All animations run until Ctrl+C.

Command Description
glyph breathe [speed] [max] [min] Breathing pulse (global brightness ramp)
glyph wave [speed] [wavelength] Traveling sine wave
glyph sweep [speed] [brightness] Fill and unfill sweep
glyph snake [speed] [length] Moving lit segment with gradient tail
glyph sparkle [speed] [density%] Random sparkle
glyph strobe [speed] [brightness] Rapid flash
glyph rain [speed] [density] Matrix-style digital rain
glyph fireworks [speed] Expanding ring bursts
glyph heartbeat [speed] Pulsing heart shape

Games

Pong
Command Description
glyph gameoflife [speed] Conway's Game of Life with wraparound and auto-reseed
glyph pong [speed] Auto-playing Pong with AI paddles
glyph dice [brightness] Animated dice roll (1-6)

Reactive

Battery
Command Description
glyph battery Display battery percentage as lit LEDs
glyph cpu [interval_ms] Live CPU load meter
glyph notify Flash pattern on incoming notifications (logcat)
glyph visualizer [speed] Audio-reactive 13-column EQ with peak dots
glyph dashboard [interval_ms] Three concentric rings: battery, CPU, network

Morse & Signals

Morse SOS
Command Description
glyph morse <text> [bright] [unit_ms] Transmit text as Morse code (dits and dahs via global brightness)

Daemon

Daemon
Command Description
glyph daemon start [--mode] Run an animation in the background
glyph daemon stop Kill the background process
glyph daemon status Check if daemon is running

Modes: --viz, --monitor, --rain, --breathe, --snake, --gameoflife, --pong, --fireworks, --sparkle

Web Panel

Web Panel
Command Description
glyph server start Launch HTTP server on port 8080
glyph server stop Stop the server
glyph server status Show server status and URL

Access the web panel at http://<phone-ip>:8080 from any browser on the same network.

Utility

Utility
Command Description
glyph map Interactive LED mapper (type index, see it light up)
glyph record <file> [interval] Record live frames to a file
glyph play <file> [speed] [loop] Play back recorded frames
glyph pipe Read 137-value frames from stdin
glyph status Device and hardware info
glyph reg Dump AW20144 register contents

Showcase Gallery


Fill

Gradient

Wave

Breathe

Snake

Rain

Fireworks

Heartbeat

Rings

Spiral

Equalizer

Alternate

Print — HI

Number — 42

Clock — Digital

Clock — Analog

Game of Life

Pong

Dice — 5

Morse — SOS

Battery — 75%

CPU — 60%

Progress — 60%

Nothing Logo

The Circular Grid

Nothing Glyph Blank Grid

The Nothing Phone (4a) Pro uses a 13x13 logical grid, but only 137 of the 169 positions have physical LEDs. The remaining 32 cells at the four corners are dead — they fall outside the circular PCB mask.

Each LED is addressed by a physical index (0-136) that runs sequentially through the grid, skipping dead cells. The kernel driver in leds_aw20144 handles the 169-to-137 mapping internally when the Nothing SDK sends a full 13x13 array. GlyphCLI bypasses this and writes the 137 physical values directly.

The full coordinate map with pixel positions, row/column assignments, and physical indices is available in glyph-svg/nothing-glyph-map.json.


How It Works

The Glyph LED matrix is driven by an AW20144 LED controller from LITEON, connected via I2C at bus 0, address 0x0020. The kernel module leds_aw20144 exposes the following sysfs interface at /sys/class/leds/matrix-leds/:

File Purpose
frame_brightness Write 137 space-separated values (0-4095), one per physical LED
brightness Global brightness (0-255)
single_brightness Set one LED: write "index value"
operating_mode Power on (1) / off (0)
effect Firmware effects (e.g. aw20144_all_rgb_on.bin)
imax Maximum current control (0-15)

Architecture

Nothing SDK Path:
  App  -->  GlyphMatrixManager  -->  IGlyphService (AIDL)  -->  NtGlyphServiceImpl  -->  sysfs
                                      com.nothing.ketchum

GlyphCLI Path:
  Shell  --------->  sysfs (direct, no middleware)

Nothing's SDK (com.nothing.ketchum) sends a 13x13 (169-element) brightness array through the IGlyphService AIDL interface. The service writes to the AW20144 kernel driver, which maps the 169 logical pixels to 137 physical LEDs. GlyphCLI skips all of that and writes the 137 values directly via sysfs.


Web Control Panel

Start the web server:

su -c glyph server start

The server binds to 0.0.0.0:8080 using toybox nc and serves a self-contained HTML panel. Access it from any browser on the same network at http://<phone-ip>:8080.

REST API

Method Endpoint Body Description
GET /api/status Returns JSON with mode, brightness, frame, battery, CPU, RAM, temp, daemon status
POST /api/cmd {"cmd":"...", "args":"..."} Execute any glyph command
POST /api/pixel {"led": N, "brightness": V} Set a single LED
POST /api/frame {"frame": [v0, v1, ...v136]} Write a full 137-value frame

The web panel provides a visual 13x13 grid where you can tap individual LEDs, launch animations, view system stats, and control the daemon — all from your browser.


Reverse Engineering Notes

The AW20144 LED controller was discovered by probing a rooted Nothing Phone (4a) Pro:

  • The aw882xx entries in logcat are the audio smart PA (speaker amplifier), not LEDs
  • The aw86927 is the haptic motor driver
  • The actual LED driver is aw20144 at I2C-0 address 0x0020
  • Chip ID reads as 0x74, hardware version T0, manufacturer LITEON
  • Decompiled GlyphNotification.apk and traced through the com.nothing.ketchum SDK
  • Device model A069P maps to SDK codename 25111p (internal name: FroggerPro)
  • The SDK uses 12-bit brightness values (0-4095) per pixel
  • frame_num 137 in dmesg confirmed the physical LED count
  • The 13x13 to 137 mapping is handled in the kernel driver, not in userspace
  • The red indicator LED is on a separate PMIC controller at /sys/class/leds/red with hardware timer blink support

Contributing

Adding new patterns: Write a new cmd_<name> function in system/bin/glyph. Use fb_clear, fb_set_led, fb_set_pixel, and fb_flush to manipulate the framebuffer. For animations, add a trap 'cmd_off; exit 0' INT TERM and loop with _sleep_ms.

SVG testing on desktop: The glyph-svg/nothing-glyph-blank.svg template can be used to preview patterns without a phone. Each <rect> has data-index, data-row, and data-col attributes for programmatic control. Run python3 generate_readme_assets.py to regenerate all showcase SVGs after making changes.

Web panel: Edit system/etc/glyph-web/panel.html for the web interface. It is a single self-contained HTML file with inline CSS and JavaScript.


License

MIT


Built by Mahdi Salmanzade — reverse-engineered from bare metal

About

Control the Nothing Phone (4a) Pro's 137 Glyph LEDs from your terminal. Games, visualizers, animations — no SDK, no sandbox, pure sysfs. Magisk module.

Resources

License

Stars

4 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors