Bare-Metal Ada on the ESP32-S3 A step-by-step guide to running Ada on the ESP32-S3 with no ESP-IDF, no FreeRTOS, and no Python.

Step 49 of 56

Console output, text and fonts

There is no Ada.Text_IO console on this target, so printing a number is a design decision — and drawing a glyph is a separate one that knows nothing about your panel.

Printing without a hosted runtime

ESP32S3.Log is the formatted-output path the examples use. It routes through the ROM printf via fixed-signature C wrappers linked into every example, so you format in Ada rather than hand-writing a glue.c helper per message:

procedure Put       (S : String);
procedure Put       (C : Character);
procedure Put_Line  (S : String := "");
procedure New_Line;
procedure Put       (N : Integer; Width : Natural := 0; Pad : Character := ' ');
procedure Put_Unsigned (N : Interfaces.Unsigned_32);
procedure Put_Hex   (N : Interfaces.Unsigned_32; Width : Natural := 0);
procedure Put_Fixed (...);

Strings are passed to C NUL-terminated, built in a small stack buffer — no secondary stack, no heap. That is what keeps this usable from the lean profiles where Ada.Text_IO is unavailable, and why it is safe to call from places a heap allocation would not be. Each call is one short esp_rom_printf.

Remember the type rule this implies, which the bus-scan sample ran into: Put_Hex takes an Interfaces.Unsigned_32, so an Integer-family value needs an explicit conversion.

Fonts, separated from panels

ESP32S3.Fonts is a panel-independent data model for proportional bitmap fonts. A Font is a light descriptor that points at flat glyph-atlas arrays generated offline by libs/esp32s3_hal/tools/gen_font.py: per-glyph metrics (advance, size, bearings, byte offset) plus packed coverage.

This package has no display dependency at all. It models glyph data and reads it through accessors; the rasterising and blitting live in the generic ESP32S3.Fonts.Render, instantiated per panel — ESP32S3.ST7789.Fonts being the worked case. So an atlas and its Font values are reusable across panels unchanged, and adding a new display type does not mean regenerating fonts.

Two coverage encodings are supported, which is how the same model serves both crisp 1-bit glyphs and anti-aliased ones. The atlas being generated offline is the important structural choice: no font parsing, no rasteriser and no heap on the device — just indexed lookups into a constant array.