Skip to content

esp32s3_8048s070c_factory_app_tools

Host-side Python utilities for manufacturing, development, and asset-pipeline work on the ESP32-S3 8048S070C board (800×480, 7-inch capacitive touch). These scripts run on a developer’s PC — never on the embedded device — and cover three concerns:

  1. Flashing — push firmware and partition images to a device over serial.
  2. Font generation — compile TTF fonts into bitmap C arrays consumed by the factory app display layer.
  3. Snapshot conversion — decode RGB565 raw captures produced by the running factory app into viewable PNG files.

Parent module: esp32s3_8048s070c_factory_app
Equivalent tools for other boards: pibot_pendant_v1_0_factory_app_tools


boards/esp32s3_8048s070c/Factory/tools/
├── flash_all.py # Multi-mode full-device flash utility
├── flash_factory.py # Single-partition factory flash utility
├── generate_font/
│ └── generate_font.py # Bitmap font C-source generator
└── raw2png/
└── snap2png.py # RGB565 raw → PNG converter

Generated Outputs

ESP32-S3 Device

Build / Binary Artifacts

Host PC (Python)

reads

reads

reads

reads

reads offset from

esptool

reads

reads offset from

esptool

reads

writes

reads

writes

flash_all.py

flash_factory.py

generate_font.py

snap2png.py

installer/bootloader.bin

installer/partitions.bin

installer/factory.bin

firmware.bin

partitions*.csv

TrueType font .ttf

snapshot .raw files

SPI Flash

UART / USB-UART bridge

fontWxH.c / .h

snapshot .png


1. flash_all.py — Multi-Mode Flash Utility

Section titled “1. flash_all.py — Multi-Mode Flash Utility”

Orchestrates all flashing scenarios from first-time board bring-up through iterative firmware development. Three mutually exclusive modes cover every use case.

FlagUse CaseWhat Gets Written
--recoveryFirst-time setup, restore after brickbootloader + partition table + factory app
--full --fw <bin>Clean full installationbootloader + partition table + factory app + main firmware
--fw <bin>Dev iterationmain firmware only → app0 at 0x20000
SPI Flash (8 MB layout)
─────────────────────────────────────────────────────────────────
0x001000 bootloader.bin (44 KB reserved space)
0x00C000 partitions.bin
0x010000 otadata
0x020000 app0 ← --fw / --full target
...
0x660000 filesystem partition
0x7A0000 factory.bin ← offset auto-detected from partitions*.csv

Note: The factory partition offset is read dynamically from the first matching partitions*.csv found in the working directory tree. The hard-coded fallback is 0x7A0000 (8 MB layout).

yes

no

yes

no

start

--port given?

use specified port

list_ports.comports

CP210x / CH340 /

CH910 / FTDI keyword

in description?

first matching port

first port in list

esptool write_flash

ParameterDefaultDescription
--port / -pauto-detectedSerial port (e.g., /dev/ttyUSB0, COM3)
--baud460800Flash baud rate
--fw / --firmware—Path to main firmware binary (required with --full)
--fw-file—Alias for --fw when used alongside --full
Terminal window
# Restore a bricked device (no firmware needed)
python flash_all.py --recovery
# Complete clean install
python flash_all.py --full --fw build/pibot_pendant.bin
# Dev iteration: firmware only
python flash_all.py --fw build/pibot_pendant.bin
# Specify port explicitly
python flash_all.py --recovery --port /dev/ttyUSB0
python flash_all.py --full --fw build/pibot_pendant.bin --port COM3

2. flash_factory.py — Factory Partition Flash Utility

Section titled “2. flash_factory.py — Factory Partition Flash Utility”

Focused utility to re-flash only the factory recovery partition. Useful when the factory app has been updated independently of the main firmware, or when a quick recovery image refresh is needed without disturbing the running firmware in app0.

Searches three CSV glob patterns in order:

partitions*.csv
boards/*/partitions*.csv
boards/*/*/partitions*.csv

Parses each CSV line looking for the column where the subtype field equals factory (case-insensitive) and returns the corresponding offset value.

ParameterDefaultDescription
--port / -pauto-detectedSerial port
--bin / -binstaller/factory.binBinary to flash
--baud460800Flash baud rate
--offset / -oauto from CSVManual override for partition offset
Terminal window
# Auto-detect everything
python flash_factory.py
# Specify port only
python flash_factory.py --port /dev/ttyUSB0
# Custom binary and offset
python flash_factory.py --bin my_factory.bin --offset 0x7A0000
# Override offset without a custom binary
python flash_factory.py --port COM4 --offset 0x7A0000

3. generate_font/generate_font.py — Bitmap Font Generator

Section titled “3. generate_font/generate_font.py — Bitmap Font Generator”

Converts a TrueType font into C source files (fontWxH.c / fontWxH.h) that the factory app’s display layer (gfx.c) uses for text rendering. See esp32s3_8048s070c_factory_app_display for how these arrays are consumed by gfx_draw_char and gfx_draw_string.

ASCII printable range 0x20 (space) through 0x7E (tilde) — 95 characters total. Non-printable characters fall back to the space glyph at runtime.

start: WxH + font.ttf

find_best_font_size

iterate pt size 6 to H+10

fit glyph within W x H cell

render_font

Pillow ImageDraw per char

measure global ascent and descent

across all 95 chars

y-center full glyph set

within target cell height

x-center each individual glyph

within target cell width

threshold: pixel greater than 127

yields 1-bit per pixel

pack bits MSB-first

bytes_per_row = ceil of W divided by 8

generate_c_files

fontWxH.h + fontWxH.c

done

Header (fontWxH.h)

#define FONT_WIDTH W
#define FONT_HEIGHT H
#define FONT_BYTES_PER_ROW /* ceil(W / 8) */
const uint8_t *fontWxH_get_glyph(char c);

Source (fontWxH.c)

static const uint8_t font_data[][bytes_per_glyph] = {
{ 0x00, 0x00, ... }, /* 0x20 ' ' */
{ 0x00, 0x18, ... }, /* 0x21 '!' */
... /* 0x7E '~' */
};
const uint8_t *fontWxH_get_glyph(char c) {
if (c < 0x20 || c > 0x7E) return font_data[0]; /* fallback: space */
return font_data[c - 0x20];
}
Cell sizeBytes/rowBytes/glyphTotal (95 chars)
6×121121,140 bytes
8×161161,520 bytes
10×202403,800 bytes
16×322646,080 bytes

These sizes fit comfortably in ESP32 flash and can be placed in DRAM for fast access.

Searches OS-specific paths for a monospace TTF (DejaVu Sans Mono, Liberation Mono, Menlo, Consolas, Courier New, Lucida Console). Exits with an actionable error message if none is found.

Perfect DOS VGA 437 by Zeh Fernando (free) gives the closest match to the CP437/DOS look used in the factory UI. Best used at multiples of 8: 8x16, 16x32, 24x48.
Download: https://www.dafont.com/perfect-dos-vga-437.font

Positional / FlagDescription
<WxH>Cell dimensions, e.g., 8x16, 10x20 (range: 4–32 wide, 6–64 tall)
[output_dir]Directory for .h / .c output files (default: .)
--font <path.ttf>Override font file; auto-detect system monospace if omitted
Terminal window
# 8×16 with auto-detected font, output to current directory
python generate_font.py 8x16 .
# 8×16 with CP437 DOS font, output into ./main
python generate_font.py 8x16 ./main --font "Perfect DOS VGA 437.ttf"
# Smaller 6×12 font into ./main
python generate_font.py 6x12 ./main
# Large font with an explicit system path
python generate_font.py 10x20 ./main --font /usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf

4. raw2png/snap2png.py — RGB565 Snapshot Converter

Section titled “4. raw2png/snap2png.py — RGB565 Snapshot Converter”

Decodes binary snapshot files captured by the running factory app (gfx_snapshot_begin / gfx_snapshot_end / snap_write in esp32s3_8048s070c_factory_app_display) and writes standard PNG images. Supports single-file and batch conversion, enabling visual QA, documentation captures, and UI layout debugging during factory testing.

Offset Size Field
─────── ──────── ────────────────────────────────────────────
0 4 bytes Width (uint32, little-endian)
4 4 bytes Height (uint32, little-endian)
8 W×H×2 B Pixel data (RGB565, row-major, little-endian)

16-bit RGB565 pixel

R5 = bits 15:11

R8 = R5 shl 3 OR R5 shr 2

G6 = bits 10:5

G8 = G6 shl 2 OR G6 shr 4

B5 = bits 4:0

B8 = B5 shl 3 OR B5 shr 2

PIL RGB tuple

(R8, G8, B8)

The (channel << upshift) | (channel >> downshift) formula replicates the top bits into the vacated low bits, producing the closest 8-bit approximation without a lookup table.

ParameterDescription
files (positional)One or more .raw files; shell glob expansion supported
-o / --outputCustom output filename (single-file mode only)

Without -o, the output filename mirrors the input with the extension replaced by .png (e.g., snap000.raw → snap000.png).

Terminal window
# Single file
python snap2png.py snap000.raw
# Batch convert all snapshots in current directory
python snap2png.py snap*.raw
# Custom output name (single file only)
python snap2png.py snap000.raw -o screenshot.png

Snapshot workflow

Build artifacts

esp32s3_8048s070c_factory_app_tools - host

Factory App - on device

esptool via UART

esptool via UART

generates

writes raw pixels

copy to host

converts

compiled into factory app

gfx.c

gfx_snapshot_begin / end

snap_write

sdcard.c

sdcard_mount / unmount

flash_all.py

flash_factory.py

generate_font.py

snap2png.py

installer/bootloader.bin

installer/partitions.bin

installer/factory.bin

partitions*.csv

fontWxH.c / fontWxH.h

snap*.raw on SD card

snap*.png on host

ESP32-S3

SPI Flash


ToolPackageInstall
flash_all.pyesptool, pyserialpip install esptool pyserial
flash_factory.pyesptool, pyserialpip install esptool pyserial
generate_font.pyPillowpip install pillow
snap2png.pyPillowpip install pillow

All tools require Python 3.6+ and run on the host only — no ESP-IDF or device connection is needed for font generation and snapshot conversion.


snap2png.pyflash_factory.pyflash_all.pyidf.py buildgenerate_font.pyDevelopersnap2png.pyflash_factory.pyflash_all.pyidf.py buildgenerate_font.pyDeveloperInitial board bring-upFactory partition refresh onlySnapshot visual QApython generate_font.py 8x16 ./mainfont8x16.c / font8x16.hidf.py build (factory + firmware)installer/*.bin + partitions.csvpython flash_all.py --full --fw firmware.bindevice running factory app + firmwarerebuild factory app onlypython flash_factory.pyfactory partition updated, firmware untouchedtrigger snapshot on device touch UIpython snap2png.py snap*.rawsnap*.png ready for inspection
ModuleRelationship
esp32s3_8048s070c_factory_appParent — full factory app for this board
esp32s3_8048s070c_factory_app_mainMain loop — drives menu, triggers snapshot actions
esp32s3_8048s070c_factory_app_displayGFX layer — produces .raw snapshot files; consumes font arrays from generate_font.py
esp32s3_8048s070c_factory_app_storageSD card — physical storage medium for .raw snapshot files
esp32s3_8048s070c_bspBSP — board-level hardware init used by the main firmware
pibot_pendant_v1_0_factory_app_toolsIdentical toolset for the PiBot Pendant v1.0 board
tools_build_scriptsProject-level resource and build toolchain (distinct scope)