# Tab5 OS

> A touchscreen environment for the M5Stack Tab5 with everyday apps, wired hardware tools, network diagnostics, and offline calculators.

Canonical page: [Tab5 OS](<https://devanmetz.com/portfolio/tab5-os/>)

Project date: Aug 2026

Updated: 2026-10-22

Category: Embedded software

Status: Open source

Tags: C, ESP-IDF, LVGL, M5Stack

- **My work:** Embedded applications and device integration
- **Hardware:** M5Stack Tab5 · ESP32-P4 touchscreen
- **Stack:** C · ESP-IDF · LVGL

- [Explore Tab5OS](<https://github.com/DevanMetz/Tab5OS>)
- [Releases](<https://github.com/DevanMetz/Tab5OS/releases/latest>)

## In short

I built Tab5 OS to use my M5Stack Tab5 for reading, notes, device inspection, and electronics work. These on-device captures show all 34 apps in a local development build newer than the v0.6.0 field beta.

![Three device screenshots showing the Tab5 OS launcher, ADC oscilloscope, and Resistor Lab with a four-band resistor.](<https://devanmetz.com/_astro/tab5-cover.Bk2-_5RU_Mmz6N.webp>)

Upper portions of three real captures—Launcher, Scope, and Resistor Lab—taken on my Tab5 on October 22, 2026, cropped and placed side by side on a neutral background, with no added UI or device frames.

## Overview 

I built Tab5 OS to turn my M5Stack Tab5 into a touchscreen environment that can move between everyday tasks and electronics work. It combines storage, networking, display and touch input with tools for inspecting signals, exchanging bytes, and saving captures.

The firmware uses ESP-IDF, Espressif’s development framework, and LVGL, a graphics library for embedded interfaces. M5Stack’s board-support code connects those applications to the ESP32-P4 microcontroller and the tablet’s hardware.

Every screenshot below came from my ST7121 tablet on October 22, 2026. Its System screen identifies the firmware as `Tab5 OS v0.6.0-3-g6d424a9-dirty`: commit `6d424a9`, three commits after the v0.6.0 tag, plus local changes. The 34-app launcher matches the newer app inventory on `main`; the tag and that commit alone have 24 apps. These captures show interfaces and their current states, not completed hardware validation.

## Launcher and screensaver 

The touch launcher scrolls through the apps, with a Home control in the shared header. The idle screensaver displays time, date, and weather forecasts.

 _The upper launcher, with everyday apps followed by hardware and Bluetooth tools._

 _The lower launcher includes the newer development apps._

 _The idle screen uses Open-Meteo weather data and wakes on touch._

## Everyday tools 

 _Notes edits and saves a local note using the touch keyboard. Personal note text is redacted._

 _Counter provides large increment, decrement, and reset controls._

 _Clock combines internet-synchronized time with persistent daily alarms and snooze; all three alarm rows are off here._

 _Settings manages brightness, screen timeout, and Wi-Fi connections. The connected network name and IP address are redacted._

 _System reports firmware, hardware, storage, and update state and provides Install stable. The Wi-Fi IP address is redacted._

## Files and reading 

 _Files browses internal storage and microSD, including viewers for saved capture graphs and serial logs. This capture shows only the storage roots._

 _Ebooks reads text files from the SD card; these are the firmware’s welcome file and three first-run Project Gutenberg classics._

 _Browser renders web pages as readable text with clickable links and HTTPS support, shown with Example Domain loaded._

## Network and online 

 _AI Chat sends messages through an authenticated HTTPS relay and supports start/stop microphone transcription with a waveform. No conversation is present here._

 _Weather looks up a city and shows current conditions, hourly forecasts, and a seven-day outlook; Milwaukee is the project’s public example._

 _HTTP Tool sends web requests with optional headers and a body and displays a bounded response preview. This GET request is prepared but has no response yet._

 _MQTT publishes and subscribes to topic-based messages through a broker, shown before connecting with the default message draft. The topic text is redacted because it includes a device-derived identifier._

 _Network provides address lookup, four-probe ping, and local service discovery through mDNS. The network name, channel, signal strength, IP, gateway, mask, and DNS details are redacted._

 _Modbus TCP reads coils, inputs, and registers using an industrial device protocol, with selectable interpretations for saved replies. The address is a firmware default and no request has been sent._

 _NTP Lab compares a time server with the tablet using four exchanges to estimate delay and clock offset without setting the clock. No samples have been taken._

 _Wake-on-LAN sends a confirmed wake packet to a configured device; a successful send cannot prove that it woke. The destination fields are empty here._

 _UDP Console sends one datagram, a network message, and previews one reply from the same peer within a bounded wait. This screen shows example bytes before an exchange._

## Bluetooth devices 

 _Govee monitors H5075 temperature and humidity broadcasts when enabled. Bluetooth is off and no readings are shown._

 _Ring connects to a COLMI R12 for wellness readings and heart-rate history. Bluetooth is off here, with no measurement displayed._

 _Cycling displays KICKR telemetry and supports SD ride logging. Bluetooth is off and no ride is running._

 _BLE GATT explores Bluetooth Low Energy devices and their exposed services and values, with explicit connections, reads, notifications, and gated writes. No scan has been started._

## Hardware and bus tools 

 _GPIO, general-purpose input/output, switches pins between pulled-up input, low output, and high output._

 _Scope plots an analog input through the ADC, an analog-to-digital converter, with eight selectable channels, trigger and calibration controls, and SD export. This capture shows a low trace on G16._

 _I2C Tool inspects a two-wire peripheral bus through address scans, register reads, watch mode, SD capture, and confirmed writes. No scan or saved read is present here._

 _Serial provides a UART or onboard RS-485 terminal with byte/text transmission, explicit line endings, logging, and captured-byte copy. The UART view is stopped with no received bytes._

 _SPI Master exchanges up to 32 bytes at a time over a clocked peripheral bus, with selectable mode and clock and received-byte copy. No transfer has been completed._

 _Signal Gen produces PWM, a repeating signal with adjustable on-time, or a single pulse on G6. Output is stopped here; pulse timing is requested rather than calibrated._

 _Servo Toy drives selectable sine or random motion on G0 with an LED driver signal on G54. Both outputs are off in this capture._

 _Ender 3 sends tank-style drive commands to a Marlin mainboard over USB CDC serial from the USB-A host port. It is searching for a printer here; live motion, disconnect/reconnect, and electrical checks remain open in the roadmap._

## Offline engineering tools 

 _Electronics calculates Ohm’s law, voltage dividers, LED resistors, and resistor-capacitor filters. The example computes current and power from voltage and resistance._

 _Byte Lab interprets and encodes bytes as text, integers, or floating-point numbers and calculates checksums to help check data integrity. This example shows six hex bytes and their checksums._

 _Subnet Lab calculates IPv4 address ranges and checks whether a peer belongs to the same subnet. All addresses shown are built-in examples; it sends no traffic._

 _Resistor Lab decodes color bands and printed surface-mount markings. The four-band example shows resistance, tolerance, and its resulting range._

 _RTU Frames builds serial Modbus read requests and validates and decodes replies offline; Serial handles actual transmission. This capture shows a generated request, with no reply decoded._

The shared byte clipboard connects Byte Lab and RTU Frames with tools such as Serial, SPI, I2C, UDP, MQTT, and BLE. It lets complete captured values move between tools without retyping; transmission still requires an explicit action in the sending app.

## Hardware and display support 

Tab5 OS targets the M5Stack Tab5 with ESP32-P4. M5Stack’s board-support layer accommodates the original ILI9881C display with GT911 touch and the newer ST7123/ST7121 family. These captures are from the ST7121 720×1280 panel; they do not establish coverage for the other display family.

The checked-in configuration preserves QIO flash access, 200 MHz PSRAM external memory, and L2-cache settings needed to keep display data flowing to the 720p panel.

External GPIO and I2C signals are **3.3 V only**. External 5 V is off at boot, and Tab5 OS has no control to enable it. The [pin-safety guide](<https://github.com/DevanMetz/Tab5OS/blob/main/docs/pin-safety.md>) documents shared pins, power, and interface limits; Servo Toy requires separate servo power and a common ground.

## Build and flash 

Use **ESP-IDF 5.4.2** in an ESP-IDF shell:

```sh
idf.py set-target esp32p4
idf.py build
```

The Windows build wrapper preserves the build tree for incremental work. App-only flashing writes the application; a full flash also writes the bootloader, partition table, and initial OTA metadata. Bootloader or storage-layout changes require the full path and a backup/migration plan, since changing the layout does not migrate internal files.

Read [Install and recovery](<https://github.com/DevanMetz/Tab5OS/blob/main/docs/install-recovery.md>) before choosing a flash command. The app-only wrapper always writes `0x20000` and does not detect the active slot. This tablet reports `ota_0 @ 0x00420000`, a legacy layout, so that wrapper must not be assumed to update its running slot. Inspect the installed partition table and active address on each tablet.

[Release assets](<https://github.com/DevanMetz/Tab5OS/releases/latest>) include the app binary, factory/recovery image, OTA manifest, `SHA256SUMS`, licenses/notices, and pinned dependency information. Verify the checksum before using a factory image; clean factory recovery erases internal settings and files.

## OTA updates 

**System > Install stable** installs a tagged stable release over Wi-Fi. OTA means over-the-air updating. The updater checks the manifest’s version, hardware compatibility, size, and permitted release URL, then verifies the downloaded image’s exact size, embedded version, and SHA-256 checksum before activation.

On a matching rollback-enabled bootloader and partition layout, the candidate stays pending until the interface and required storage/settings have remained healthy for 30 seconds. Rollback can return to the previous image if that validation fails. Updates preserve device settings, including device-specific chat configuration kept separate from public release binaries.

The [OTA contract](<https://github.com/DevanMetz/Tab5OS/blob/main/docs/ota-manifest.md>) describes these checks and their limits. Independent release signatures and further physical install/rollback tests remain open work.

## Remote-desktop capture 

These 37 screenshots were captured over USB Serial/JTAG on October 22, 2026, around 12:52–12:59 PM CDT, using a small pyserial client on COM7. They are 720×1280 device framebuffer captures, not desktop interface renders.

The protocol sends 10-byte `T5` command packets: kind 1 requests a frame, and kind 2 sends touch state and coordinates. The device replies with a 20-byte `T5RD` header carrying version, type, encoding, flags, dimensions, payload size, and frame number, followed by run-length pairs of a pixel count and an RGB565 color. RGB565 packs red, green, and blue into 16 bits. The repository’s [remote desktop client](<https://github.com/DevanMetz/Tab5OS/blob/main/tools/remote_desktop.py>) implements this protocol and maps mouse input to touch:

```sh
python tools/remote_desktop.py --port COM7 --scale 1
```

Before publishing, I covered personal note text, Wi-Fi identity and address details, and MQTT’s device-derived topic with solid opaque fills. Each affected caption identifies the redaction. The images were then converted to WebP; the cover shows the upper portions of three real captures, cropped and placed side by side on a neutral background, with no added UI or device frames.

## Source and current state 

The [Apache-2.0 source repository](<https://github.com/DevanMetz/Tab5OS>) contains the applications, board integration, build tools, release workflow, and documentation. Managed dependencies are pinned, and the M5Stack and Espressif components retain their attribution.

As of this capture, **v0.6.0 is the latest tagged field beta**. Network, Electronics, Byte Lab, Modbus TCP, NTP Lab, Wake-on-LAN, Subnet Lab, UDP Console, Resistor Lab, and RTU Frames are the ten additional launcher entries in this development build and on `main`; they are not in v0.6.0.

The [README](<https://github.com/DevanMetz/Tab5OS#status>), [roadmap](<https://github.com/DevanMetz/Tab5OS/blob/main/ROADMAP.md>), and [hardware smoke checklist](<https://github.com/DevanMetz/Tab5OS/blob/main/docs/hardware-smoke-checklist.md>) distinguish implemented features from measured coverage. Open work includes the second display family, external peripheral and electrical checks, USB brownout follow-up, remaining HTTP checks, storage fault/recovery tests on hardware, repeated OTA/rollback cycles, and an eight-hour mixed-use soak. This screenshot set does not close those tests.

## FAQ

### Which hardware does Tab5 OS target?

Tab5 OS targets the M5Stack Tab5 with ESP32-P4. The page's device captures come from an ST7121 720×1280 panel and do not establish coverage for the other display family.

### Are all the pictured apps included in v0.6.0?

No. The screenshots show a local development build with 34 apps. Ten additional launcher entries are in that build and on main but are not in the v0.6.0 field beta.

### How do stable updates work?

System > Install stable downloads a tagged release over Wi-Fi. The updater checks compatibility and manifest details, then verifies the image's size, embedded version, and SHA-256 checksum before activation.

### Can the external pins accept 5 V signals?

External GPIO and I2C signals are 3.3 V only. External 5 V is off at boot, and Tab5 OS has no control to enable it.

## Related reading

- [nRF54L15 Support](<https://devanmetz.com/portfolio/nrf54l15-support/index.md>)
- [6×10 WS2812 Matrix for XIAO nRF54L15](<https://devanmetz.com/portfolio/ws2812-matrix-xiao/index.md>)
- [OpenFloat Archery](<https://devanmetz.com/portfolio/openfloat-archery/index.md>)
