API reference
Everything in ros.h that an app can use: 250 functions and variables the firmware exports, and the header's types, constants and macros - from the app kit of Reload OS 1.4.0 (app interface 2). The descriptions are the header's own comments.
Threading: every LVGL call happens inside an LVGL callback (event, timer - they run on the LVGL task) or between ros_lock() / ros_unlock(). Nothing that waits belongs on the LVGL task - see the rules.
#Screen, theme and the LVGL lock
A big static variable in PSRAM instead of the scarce internal RAM (CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY). Only for what tasks use: never something an interrupt handler touches, nothing needed before app_main(). It starts as zeros like any other and cannot have an initialiser.
#define ROS_BIG_BSS EXT_RAM_BSS_ATTR#define ROS_NAME "Reload OS"ROS_VERSION: the release, from version.txt (main/CMakeLists.txt) - also the app descriptor's version
#ifndef ROS_VERSION
#define ROS_VERSION "dev"
#endifScreen geometry: the panel is 1024x600 (JC4880P443: 480x800, scanned vertically). Mounted the panel's own way it is used as it is; the other way (setting "orientation", Settings > Display, applied at the next start) the display pipeline turns the UI (main.c): 600x1024 on a 7" board vertical, 800x480 on the JC4880P443 horizontal. ROS_SCR_W / ROS_SCR_H are therefore values, not constants.
#define ROS_PANEL_W ROS_BOARD_PANEL_W /* the panel as it scans (its frame buffer); the UI may be turned */
#define ROS_PANEL_H ROS_BOARD_PANEL_Hextern int ros_scr_w, ros_scr_h;#define ROS_SCR_W (ros_scr_w)
#define ROS_SCR_H (ros_scr_h)
#define ROS_PORTRAIT (ros_scr_h > ros_scr_w)
#define ROS_NARROW (ros_scr_w < 560) /* the JC4880P443 vertical (480 px): one control a line, short texts */
#define ROS_DLG_W(w) ((w) < ros_scr_w - 24 ? (w) : ros_scr_w - 24) /* a dialog width that fits either way */A pointer position as the UI sees it -> what a pointer device must report: LVGL turns every pointer's coordinates for a turned display, so one that is already in UI coordinates (remote desktop, USB mouse, probe) has to be turned back first.
void ros_pointer_raw(int32_t *x, int32_t *y);enum { ROS_ORIENT_HORIZONTAL, ROS_ORIENT_VERTICAL, ROS_ORIENT_VERTICAL_FLIPPED, ROS_ORIENT_COUNT };#define ROS_BAR_H 44Theme: dark or light (setting "theme", Settings > Display; applied at the next start). The ROS_C_* names read the palette in use, so they are values, not constants: no static initialisers.
typedef struct {
uint32_t bg, surface, surface2, border, text, muted, dim, accent, accent2, ok, warn, err;
} ros_palette_t;extern const ros_palette_t *ros_pal;
void ros_theme_apply(int light); /* before the UI is built */#define ROS_C_BG (ros_pal->bg)
#define ROS_C_SURFACE (ros_pal->surface)
#define ROS_C_SURFACE2 (ros_pal->surface2)
#define ROS_C_BORDER (ros_pal->border)
#define ROS_C_TEXT (ros_pal->text)
#define ROS_C_MUTED (ros_pal->muted)
#define ROS_C_DIM (ros_pal->dim) /* status icons that are off */
#define ROS_C_ACCENT (ros_pal->accent)
#define ROS_C_ACCENT2 (ros_pal->accent2)
#define ROS_C_OK (ros_pal->ok)
#define ROS_C_WARN (ros_pal->warn)
#define ROS_C_ERR (ros_pal->err)LVGL lock for code outside LVGL event/timer callbacks (recursive). timeout_ms = 0 waits forever. Returns false on timeout.
bool ros_lock(uint32_t timeout_ms);
void ros_unlock(void);#Apps
typedef struct ros_app {
const char *name;
const char *icon; /* LV_SYMBOL_* glyph */
uint32_t color; /* launcher tile colour */
const void *(*image)(void); /* optional: a picture for the tile instead of the glyph */
bool image_on_white; /* the picture is a logo: white tile instead of the colour */
void (*create)(lv_obj_t *body); /* build UI inside `body` */
void (*destroy)(void); /* optional: stop timers / free memory */
bool (*back)(void); /* optional: handle "back" (edge swipe) in-app; false = go home */
} ros_app_t;Apps on the SD card (ros_elfapp.c): an ELF file in /sdcard/apps/ whose main(argc, argv) stores a pointer to its ros_elfapp_t in *(const ros_elfapp_t **)argv[0]. ROS_ELFAPP_ABI changes whenever ros_app_t, the meaning of the exported API, or the layout of a struct of this header an app uses changes (new struct fields go at the end instead); an app made for another number is refused. Template: elfapps/hello/; build: tools/elfapp.sh <name>.
#define ROS_ELFAPP_ABI 2What the launcher shows for an app on the SD card - read from the file at start, without loading the app: a section ".ros_meta" holding one of these. Without it the tile is named after the file.
typedef struct {
char magic[4]; /* "ROSM" */
uint32_t version; /* ROS_ELFAPP_META_VERSION */
char name[24]; /* the tile's name; an app with a built-in app's name replaces it */
char icon[16]; /* an LV_SYMBOL_* glyph, or "@name" for a drawn icon (ros_icon()) */
uint32_t color; /* the tile's colour */
uint32_t flags; /* ROS_ELFAPP_ON_WHITE */
} ros_elfapp_meta_t;#define ROS_ELFAPP_META_VERSION 2
#define ROS_ELFAPP_ON_WHITE 1u /* the tile's picture (ROS_ELFAPP_TILE) is a logo: a white tile */
#define ROS_ELFAPP_META_FLAGS(name_, icon_, color_, flags_) \
__attribute__((section(".ros_meta"))) const ros_elfapp_meta_t ros_elfapp_meta = \
{ { 'R', 'O', 'S', 'M' }, ROS_ELFAPP_META_VERSION, name_, icon_, color_, flags_ }
#define ROS_ELFAPP_META(name_, icon_, color_) ROS_ELFAPP_META_FLAGS(name_, icon_, color_, 0)Optional: a picture for the tile instead of the glyph. The PNG (at most 64 KB) goes into the file's section ".ros_tile", which is not loaded with the app - the launcher reads it at start. file_ is its path as a string, from the app's CMakeLists.txt.
#define ROS_ELFAPP_TILE(file_) \
__asm__(".pushsection .ros_tile, \"\", @progbits\n.incbin \"" file_ "\"\n.popsection")typedef struct {
uint32_t abi; /* ROS_ELFAPP_ABI it was built with */
ros_app_t app;
const char *board; /* ROS_BOARD_SHORT it was built for: the pins are the board's */
volatile int *tasks; /* its tasks still running (NULL: none). The code is unloaded
* only when this is 0 - end them with ros_task_end(). */
void (*unload)(void); /* optional: right before the code goes (no task of it left) -
* free what it keeps across opens (queues, mutexes ...): every
* load starts with fresh variables, so that would leak */
const ros_elfapp_meta_t *meta; /* &ros_elfapp_meta (ROS_ELFAPP_META): keeps the section in the file */
} ros_elfapp_t;The end of a task that counts itself in *live (an app on the SD card must, see ros_elfapp_t.tasks): the count goes down here, in the firmware, so the task never returns into code that may be gone. caps: the task was made with xTaskCreate...WithCaps. Does not return.
void ros_task_end(volatile int *live, bool caps) __attribute__((noreturn));The product this firmware is built as (products/<product>/product.c; -D ROS_PRODUCT=..., see products/README.md): its name and the apps on its launcher, in their built-in order (at most 16 - the shell keeps 8 places for the SD card's apps).
extern const char *const ros_product_name;
extern const ros_app_t *const ros_product_apps[];
extern const int ros_product_app_count;In ros.h for the firmware itself, not exported to apps: app_settings, app_wifi, app_monitor, app_files, app_ethernet, app_camera, app_recorder, app_usb, app_idcard, app_factory, ros_factory_log, ros_elfapp_merge, ros_elfapp_release.
#Shell
int ros_app_count(void); /* launcher apps, for the auto-start choice */
const ros_app_t *ros_app_at(int i);
void ros_open_app(const ros_app_t *app);An app screen shown inside another app (Settings pages): counts as active for ros_app_is_active(). NULL when it goes away.
void ros_app_embed(const ros_app_t *app);Settings pages (Android-style: every driver's settings in one app)
enum {
ROS_SETTINGS_WIFI, ROS_SETTINGS_ETHERNET, ROS_SETTINGS_HOTSPOT, ROS_SETTINGS_BLUETOOTH, ROS_SETTINGS_REMOTE,
ROS_SETTINGS_DISPLAY, ROS_SETTINGS_SOUND, ROS_SETTINGS_STORAGE, ROS_SETTINGS_USB,
ROS_SETTINGS_TIME, ROS_SETTINGS_ABOUT,
/* Tools (1.4): apps that were on the launcher - their screen inside Settings */
ROS_SETTINGS_CAMERA, ROS_SETTINGS_MONITOR, ROS_SETTINGS_RECORDER, ROS_SETTINGS_IDCARD,
};void ros_open_settings(int page); /* -1 = the category list */
void ros_go_home(void);
bool ros_app_is_active(const ros_app_t *app);
void ros_toast(const char *fmt, ...);
void ros_statusbar_show(bool show); /* hidden = no redraws at all (full-screen video overlay) */Small UI helpers so apps look consistent
lv_obj_t *ros_ui_card(lv_obj_t *parent);
lv_obj_t *ros_ui_round_corners(lv_obj_t *box, int radius, uint32_t outside_color); /* cheap clip_corner */
lv_obj_t *ros_ui_button(lv_obj_t *parent, const char *text, uint32_t color);An embedded PNG decoded once (kept for good; RGBA -> LVGL's ARGB8888). NULL if it can't be.
const void *ros_ui_png(const uint8_t *start, const uint8_t *end);a drawn icon by name (main/assets/icons, tools/mkicons.py), e.g. "sun"; NULL if there is none
const void *ros_icon(const char *name);that icon as an lv_image tinted to `color` (white drawings)
lv_obj_t *ros_ui_icon(lv_obj_t *parent, const char *name, uint32_t color);
lv_obj_t *ros_ui_list_note(lv_obj_t *list, const char *text); /* a muted text line in a list */put a drawn icon in front of a button's text (tinted like the text)
void ros_ui_button_icon(lv_obj_t *btn, const char *name);
lv_obj_t *ros_ui_keyboard(lv_obj_t *parent); /* the OS keyboard: big keys, digit row, key preview, click */
void ros_ui_keyboard_light(lv_obj_t *kb); /* its colours for a light screen */
lv_obj_t *ros_ui_label(lv_obj_t *parent, const lv_font_t *font, uint32_t color, const char *text);In ros.h for the firmware itself, not exported to apps: ros_shell_start.
#Settings (NVS)
IPv4 configuration: on = static address, else DHCP. Strings are dotted quads ("" = unset).
typedef struct {
bool on;
char ip[16], mask[16], gw[16], dns[16];
} ros_ipv4_t;Shared "IP settings" dialog (Ethernet and Wi-Fi pages). `current` pre-fills the fields when nothing is saved yet (the DHCP lease). on_save runs in the LVGL task after validation.
typedef void (*ros_ipv4_save_cb_t)(const ros_ipv4_t *cfg);void ros_ipv4_dialog(const char *title, const ros_ipv4_t *saved, const ros_ipv4_t *current,
const char *note, ros_ipv4_save_cb_t on_save);
void ros_ipv4_dialog_close(void);typedef struct {
int brightness; /* 5..100 % */
int volume; /* 0..100 % */
int tz_index; /* index into ros_timezones */
bool wifi_enabled;
bool remote_enabled; /* browser remote desktop, restored at boot */
int usb_port; /* USB host port: 0 = USB Native (HS), 1 = USB_OTG (FS); applied at boot */
bool usb_hub; /* high-speed port runs at full speed so FS devices work behind a hub; at boot */
ros_ipv4_t eth; /* Ethernet: static address (on) or DHCP */
ros_ipv4_t wifi; /* Wi-Fi: static address, only on the network below */
char wifi_static_ssid[33];
int screen_timeout; /* index into ros_screen_timeouts (0 = never) */
int printer_lang; /* ros_prn_lang_t; ROS_PRN_AUTO = from the printer's device ID */
int printer_dots; /* receipt printers: dots per line, 0 = auto (384 = 58 mm, 576 = 80 mm) */
bool hotspot_on; /* Wi-Fi access point (ros_wifi.c) */
bool hotspot_share; /* share the board's internet (Ethernet / Wi-Fi) with hotspot clients: NAT */
char hotspot_ssid[33];
char hotspot_pass[65];/* "" = open network; else 8..63 characters, WPA2 */
int bp_baud; /* serial speed of a blood-pressure monitor (a product app's setting) */
char remote_user[25]; /* remote desktop login (ros_remote.c) */
char remote_pass[33]; /* "" = not made yet: a random one is created when the remote desktop first starts */
int theme; /* 0 dark, 1 light (ros_pal) */
char ntp_server[64]; /* SNTP server, "" = pool.ntp.org */
char app_order[256]; /* launcher order: app names, comma separated (others follow); "" = built-in */
char autostart[24]; /* app opened by itself after boot (its launcher name), "" = home screen */
int orientation; /* ROS_ORIENT_*: how the device is mounted; applied at the next start */
bool bt_enabled; /* Bluetooth LE (ros_bt.c): restored at boot */
bool bt_visible; /* advertise the name below, so phones and PCs see the device */
char bt_name[25]; /* "" = not made yet: ReloadOS-XXXX (from the MAC) when Bluetooth is first switched on */
bool ram_disk; /* the 8 MB RAM disk in PSRAM (/ram, also a USB drive for a PC); applied at boot */
uint8_t panel; /* which panel a board sold with more than one has (ROS_BOARD_PANEL_VARIANTS; JC8012P4A1:
* 0 = the vendor's New_Panel, 1 = Old_Panel); applied at boot */
/* New fields go HERE, at the end: SD card apps use this struct by offset (a product app reads bp_baud,
* theme ...). A field in the middle moves the ones after it under every app built before - or
* raise ROS_ELFAPP_ABI. The same for every struct of this header an app uses. */
} ros_settings_t;Screen timeout choices (seconds, 0 = never) and labels for a dropdown
extern const int ros_screen_timeouts[];
extern const char *const ros_screen_timeout_labels; /* "Never\n30 seconds\n..." */#define ROS_SCREEN_TIMEOUT_COUNT 6void ros_keep_awake(void); /* call periodically while something should keep the screen on (video) */Why the last boot happened. crash = panic / watchdog / brownout.
const char *ros_reset_reason(bool *crash);In ros.h for the firmware itself, not exported to apps: ros_ipv4_valid, ros_ipv4_mask_valid, ros_back.
#Device health (ros_health.c)
For devices nobody watches: restart counters, what the last crash was, a crash-loop guard (safe mode: no auto start app) and a watchdog on the UI task.
typedef struct {
uint32_t boots, crashes, brownouts; /* since the first start of a release with this record (1.0.0) */
uint8_t streak; /* crashes in a row, each soon after its start */
bool crashed; /* this start follows a crash (panic / watchdog) */
bool safe_mode; /* this start: a crash loop - the auto start app is not opened */
char last[224]; /* the last crash on record, one line; "" = none */
} ros_health_t;void ros_health_ui_start(void); /* LVGL context, when the shell is up: UI watchdog, "settled" timer */
const ros_health_t *ros_health(void);
void ros_health_app(const char *name); /* the app on screen (NULL = home screen): goes into a crash record */typedef struct {
const char *label;
const char *posix;
} ros_tz_t;extern const ros_tz_t ros_timezones[];
extern const int ros_timezone_count;void ros_settings_load(void);
void ros_settings_save(void);
ros_settings_t *ros_settings(void);
void ros_apply_brightness(int pct);
void ros_apply_timezone(int idx);In ros.h for the firmware itself, not exported to apps: ros_health_init, ros_health_clear.
#Storage
Three FAT volumes, each usable locally or exposed to a PC over USB_OTG (ros_usbdev.c). While a PC has them, they are NOT available locally (ros_vol_available() == false).
#define ROS_SD_MOUNT "/sdcard"
#define ROS_FFAT_MOUNT "/ffat"
#define ROS_RAM_MOUNT "/ram"typedef enum { ROS_VOL_SD, ROS_VOL_FFAT, ROS_VOL_RAM, ROS_VOL_COUNT } ros_vol_t;bool ros_vol_present(ros_vol_t v); /* the medium exists (card inserted, partition found) */
bool ros_vol_available(ros_vol_t v); /* mounted in Reload OS right now */
const char *ros_vol_path(ros_vol_t v);
bool ros_vol_stats(ros_vol_t v, uint64_t *total, uint64_t *free_bytes);Erase and re-create the volume's FAT (SD: FAT32, 32 KB clusters). Blocking - several seconds for the SD card; call from a task. Refused while a PC has the volumes.
esp_err_t ros_vol_format(ros_vol_t v);esp_err_t ros_usbdev_start(void); /* USB mass-storage device on USB_OTG */
bool ros_usbdev_pc_connected(void); /* a PC currently owns the volumes */
bool ros_sd_mounted(void);
uint64_t ros_sd_total_bytes(void);
uint64_t ros_sd_free_bytes(void);In ros.h for the firmware itself, not exported to apps: ros_usbdev_enabled, ros_usbdev_generation, ros_storage_init.
#Animations (ros_anim.c)
A looping animation made from a GIF by tools/mkanim.py. Returns an lv_image (NULL: bad data or no memory) that is paused until ros_anim_run(). The data must outlive the object. LVGL task only.
lv_obj_t *ros_anim_create(lv_obj_t *parent, const uint8_t *data, size_t len);The same from a file: /ffat/anim/<name>, else /sdcard/anim/<name> (8.3 name), read into PSRAM. keep: the bytes stay loaded for the session (an app that is opened again and again).
lv_obj_t *ros_anim_create_file(lv_obj_t *parent, const char *name, bool keep);
void ros_anim_run(lv_obj_t *anim, bool run); /* true: play from the first frame; false: pause */#Audio
esp_err_t ros_audio_init(void);
bool ros_audio_ready(void);
void ros_audio_set_volume(int pct);
void ros_audio_tone(float freq_hz, int duration_ms); /* non-blocking */
void ros_audio_click(void);
esp_err_t ros_audio_play_wav(const char *path); /* 16-bit mono WAV, non-blocking */A whole WAV file in memory, 16 kHz mono, 16-bit PCM or IMA ADPCM; non-blocking, replaces what plays. The memory must stay valid until it ends (built-in voice prompts).
esp_err_t ros_audio_play_mem(const void *wav, size_t len);A sound file from a drive: MP3 (any bit rate, 32-48 kHz, mono / stereo) or WAV (PCM 8 / 16-bit, mono / stereo, any rate), decoded in its own task and played through the stream (16 kHz mono on the speaker). Non-blocking; replaces what plays; ros_audio_stop() ends it, ros_audio_playing() says whether it runs.
esp_err_t ros_audio_play_file(const char *path);
void ros_audio_stop(void); /* interrupt tone / WAV / file playback */
bool ros_audio_idle(void); /* nothing queued, nothing playing (memory a clip came from may go) */PCM stream (video soundtracks): any rate, 8/16-bit, mono/stereo in; converted to the speaker's 16 kHz mono. UI click tones are ignored while a stream plays. The clock counts what has actually been played (minus output latency) - use it as the A/V master clock.
esp_err_t ros_audio_stream_start(int rate, int channels, int bits); /* starts paused */
size_t ros_audio_stream_write(const void *pcm, size_t bytes); /* never blocks; bytes taken */
int ros_audio_stream_buffered_ms(void);
void ros_audio_stream_pause(bool pause);
void ros_audio_stream_format(int rate, int channels, int bits); /* change the input format, keep playing */
int64_t ros_audio_stream_clock_us(void);
void ros_audio_stream_reset(void); /* drop buffer, clock to 0 */
void ros_audio_stream_stop(void);
bool ros_audio_playing(void);In ros.h for the firmware itself, not exported to apps: ros_audio_stream_free_ms.
#Microphone
Called on the mic task with each 20 ms block (16 kHz, 16-bit mono)
typedef void (*ros_mic_cb_t)(const int16_t *samples, size_t count, void *user);bool ros_mic_ready(void);
esp_err_t ros_mic_start(ros_mic_cb_t cb, void *user); /* cb may be NULL (level meter only) */
void ros_mic_stop(void); /* also finalises any recording */
int ros_mic_level(void); /* 0..100, peak -60..0 dBFS */
void ros_mic_set_gain(float db);
esp_err_t ros_mic_record_start(const char *path); /* WAV to SD; mic must be started */
uint32_t ros_mic_record_stop(void); /* returns recorded length in ms */
bool ros_mic_recording(void);
uint32_t ros_mic_record_ms(void);#Wi-Fi
typedef enum {
ROS_WIFI_STARTING,
ROS_WIFI_UNAVAILABLE, /* co-processor did not respond */
ROS_WIFI_OFF,
ROS_WIFI_IDLE,
ROS_WIFI_CONNECTING,
ROS_WIFI_CONNECTED,
} ros_wifi_state_t;typedef struct {
char ssid[33];
int8_t rssi;
bool secure;
} ros_wifi_ap_t;void ros_wifi_start(void); /* spawns init task */
ros_wifi_state_t ros_wifi_state(void);
const char *ros_wifi_ssid(void);
const char *ros_wifi_ip(void);
int ros_wifi_rssi(void);
esp_err_t ros_wifi_set_enabled(bool on);
esp_err_t ros_wifi_scan(ros_wifi_ap_t *out, int max, int *found); /* blocking */
esp_err_t ros_wifi_connect(const char *ssid, const char *password);Static IPv4 for Wi-Fi (Android-style, per network): ros_settings()->wifi applies only while connected to ros_settings()->wifi_static_ssid; any other network uses DHCP.
esp_err_t ros_wifi_apply_ip(void); /* apply now (no reconnect) */
void ros_wifi_ip_info(ros_ipv4_t *out); /* current address / mask / gateway / DNS; on = static */
void ros_wifi_disconnect(void);Hotspot: the C6 as an access point (AP, or AP + station), 192.168.4.1/24 with DHCP; with sharing on, clients reach the internet through the board (lwIP NAPT over Ethernet or Wi-Fi)
#define ROS_HOTSPOT_IP "192.168.4.1"esp_err_t ros_hotspot_set(bool on); /* saved; LVGL or worker context */
esp_err_t ros_hotspot_config(const char *ssid, const char *pass, bool share); /* saved, re-applied */
bool ros_hotspot_running(void);
int ros_hotspot_clients(void);
const char *ros_hotspot_uplink(void); /* "Ethernet" / "Wi-Fi" / "" (no internet to share) */#Bluetooth LE (ros_bt.c)
The controller is the ESP32-C6's, over the esp-hosted link; the host stack (NimBLE) runs on the P4. Nothing is started while it is off. No pairing and no profiles yet: the device is visible under its name and lists the devices nearby.
typedef enum {
ROS_BT_OFF,
ROS_BT_STARTING,
ROS_BT_ON,
ROS_BT_STOPPING,
ROS_BT_UNAVAILABLE, /* the C6 does not answer, or its firmware has no Bluetooth: ros_bt_status() */
} ros_bt_state_t;typedef struct {
uint8_t addr[6]; /* as NimBLE has it: least significant byte first */
int8_t rssi;
char name[30]; /* "" = the device did not send one */
} ros_bt_dev_t;void ros_bt_start(void); /* boot: its task; on if the setting is */
bool ros_bt_supported(void); /* the C6's firmware has Bluetooth (known once the link is up) */
esp_err_t ros_bt_set_enabled(bool on); /* saved; returns at once - watch ros_bt_state() */
ros_bt_state_t ros_bt_state(void);
const char *ros_bt_status(void); /* why it is unavailable, "" otherwise */
const char *ros_bt_address(void); /* "AA:BB:CC:DD:EE:FF" while on, else "" */
esp_err_t ros_bt_set_name(const char *name); /* 1-24 printable ASCII characters; saved, applied at once */
void ros_bt_set_visible(bool on); /* saved, applied at once */
int ros_bt_connections(void); /* devices connected to this one */
esp_err_t ros_bt_scan(int seconds); /* look for devices nearby (1-60 s) */
bool ros_bt_scanning(void);
int ros_bt_devices(ros_bt_dev_t *out, int max); /* found so far: named ones first, then by signal. LVGL task */
uint32_t ros_bt_generation(void); /* changes with the state, the list, the connections */#Display performance
typedef struct {
const char *name;
float fps;
float avg_ms; /* render + flush per refresh */
float max_ms;
} ros_perf_result_t;typedef void (*ros_perf_done_cb_t)(const ros_perf_result_t *results, int count);void ros_perf_init(void); /* call once with the display lock held */
bool ros_perf_benchmark(ros_perf_done_cb_t done); /* LVGL context; results also logged */
void ros_perf_counters(uint32_t *frames, uint64_t *us); /* all LVGL refreshes so far, total time */
void ros_perf_overlay(bool show); /* FPS / refresh ms / CPU per core */
bool ros_perf_overlay_visible(void);In ros.h for the firmware itself, not exported to apps: ros_perf_benchmark_running.
#Remote desktop
See and drive this screen from a browser (concept: RLD_Remote). MJPEG stream from the hardware JPEG encoder on port 81, page + touch on port 80. Plain HTTP, no login.
esp_err_t ros_remote_start(void);
void ros_remote_stop(void);
void ros_remote_set_enabled(bool on); /* start/stop and remember the choice */New login: user 1-24 of A-Z a-z 0-9 _ . -, password 6-32 printable characters without spaces. Everybody who is logged in is logged out. ESP_ERR_INVALID_ARG if they don't fit.
esp_err_t ros_remote_set_login(const char *user, const char *pass);
bool ros_remote_running(void);
const char *ros_remote_url(void); /* "http://a.b.c.d/" once an interface has an IP */
int ros_remote_viewers(void);In ros.h for the firmware itself, not exported to apps: ros_remote_frames, ros_remote_snapshot, ros_remote_snapshot_done, ros_remote_touch, ros_probe_start, ros_probe_put.
#JPEG codec (hardware)
void ros_jpeg_init(void);
jpeg_decoder_handle_t ros_jpeg_decoder(void);
esp_err_t ros_jpeg_encode(const jpeg_encode_cfg_t *cfg, const uint8_t *in, uint32_t in_size,
uint8_t *out, uint32_t out_size, uint32_t *out_len);#Heap watch (ros_heap.c)
ESP32-C6 Wi-Fi co-processor firmware (ros_cpfw.c): version, update over SDIO from the SD card
#define ROS_CPFW_PATH "/sdcard/esp32c6_hosted.bin"void ros_cpfw_start(void); /* asks the C6 for its version (background) */
const char *ros_cpfw_version(void);
bool ros_cpfw_file_present(void);
esp_err_t ros_cpfw_update(void); /* starts the update; P4 restarts when done */
esp_err_t ros_cpfw_update_file(const char *path); /* the same from any volume */
int ros_cpfw_progress(const char **msg); /* 0..100, -1 = idle; msg: stage or error */Battery-backed clock (ros_rtc.c): the P4's LP timer on VDD_BAT (MaTouch), or the RX8025T clock chip (JC1060P470C)
typedef enum { ROS_CLOCK_UNSET, ROS_CLOCK_BATTERY, ROS_CLOCK_NETWORK, ROS_CLOCK_MANUAL } ros_clock_src_t;void ros_rtc_init(void); /* early in boot: restore / report the clock */
void ros_rtc_on_sync(struct timeval *tv); /* SNTP sync callback */
void ros_rtc_tz_changed(void);
void ros_rtc_set_manual(time_t t); /* set by hand (no internet): clock, backup, clock chip */
time_t ros_rtc_last_sync(void); /* last network sync, 0 = none since boot */ /* after ros_apply_timezone() with a new zone */
ros_clock_src_t ros_rtc_source(void);
const char *ros_rtc_status(void); /* one line for Settings */
bool ros_rtc_rc_ppm(float *ppm, int *minutes); /* live: internal RC vs main crystal since boot */
const char *ros_rtc_drift(void); /* accuracy at the last network sync after boot, "" if none */void ros_heap_init(void); /* failed-allocation log + low-RAM watch */
void ros_heap_report(const char *why); /* heaps and every task's stack, to the log */
void ros_lvmem_usage(size_t *bytes, size_t *blocks); /* what LVGL holds now (ros_lvmem.c) */
void ros_cpu_report(int ms, char *out, size_t n); /* per-task CPU over ms, to the log and out */In ros.h for the firmware itself, not exported to apps: ros_rtc_save, ros_heap_failures.
#Images (ros_image.c)
Decode a JPEG / PNG / BMP file, scaled to fit bw x bh (at most max_scale up), into BGR888 (LVGL RGB888 order) in PSRAM; caller frees. iw/ih: the image's own size. Worker tasks only.
uint8_t *ros_image_decode(const char *path, int bw, int bh, float max_scale, int *ow, int *oh, int *iw, int *ih,
const char **err);
bool ros_ext_is(const char *name, const char *list); /* list: "jpg,jpeg,png" */Same, for a baseline JPEG already in memory (e.g. an ID card photo)
uint8_t *ros_image_decode_jpeg_mem(const uint8_t *data, size_t len, int bw, int bh, float max_scale, int *ow,
int *oh, int *iw, int *ih, const char **err);#MySQL client (ros_mysql.c)
typedef struct {
char host[64];
int port; /* 0 = 3306 */
char user[33], pass[65];
} ros_mysql_cfg_t;Connect, log in (mysql_native_password), run one statement, quit. Plain TCP. err: a short reason on failure. Blocking with timeouts - worker tasks only.
esp_err_t ros_mysql_exec(const ros_mysql_cfg_t *cfg, const char *sql, char *err, size_t err_n);#Firmware update (ros_ota.c)
typedef struct {
char project[32], version[32], built[24], idf[32];
uint32_t size;
bool ours; /* a Reload OS build */
bool legacy; /* ... from before 1.0.0: it does not say which board it is for */
} ros_ota_info_t;#define ROS_PROJECT_PREFIX "reload_os" /* project name: reload_os_<board> (root CMakeLists.txt) */
#define ROS_OTA_PATH "/sdcard/reload_os.bin" /* Settings > About > Update from SD looks here ... */
#define ROS_OTA_PATH_UPLOAD "/sdcard/update.bin" /* ... then here (where POST /ota stores it) */void ros_ota_start(void); /* boot: report the slot, confirm a new image after 20 s */
const char *ros_ota_sd_file(void); /* the update file on the SD card, NULL if none */
esp_err_t ros_ota_check_file(const char *path, ros_ota_info_t *info, const char **why);
esp_err_t ros_ota_install_file(const char *path); /* starts it; the device restarts when done */
void ros_ota_offer(const char *path); /* LVGL: check it and ask on screen before installing */
void ros_ota_offer_async(const char *path); /* same, from any task */
void ros_ota_ui_tick(void); /* LVGL: install dialog + progress overlay */
int ros_ota_progress(const char **msg); /* 0..100, -1 = idle; msg: stage or last error */
const char *ros_ota_running(void); /* "1.0.0 (slot ota_0, built ...)" */#File operations
Blocking - call from a worker task. Work across volumes and on whole folders. Name clashes in the destination get "name (2).ext". A cancelled or failed copy leaves nothing behind.
typedef struct {
volatile bool cancel;
volatile uint64_t total_bytes, done_bytes;
volatile int total_files, done_files;
char current[64]; /* name being processed */
} ros_fsop_progress_t;bool ros_fs_valid_name(const char *name);
esp_err_t ros_fs_unique(const char *dir, const char *name, char *out, size_t n);
esp_err_t ros_fs_copy(const char *src, const char *dst_dir, bool move, ros_fsop_progress_t *p,
char *dst_out, size_t dst_n); /* move: rename on the same volume;
ESP_ERR_NOT_FINISHED: moved across volumes, but the original is not all gone */
esp_err_t ros_fs_delete(const char *path, ros_fsop_progress_t *p);#License (ros_license.c)
A free device shows "Reloader Co.,Ltd." on every screen until it is activated: one payment per device through Reloader's license server (server/license/), or a license.txt on the SD card.
typedef enum { ROS_LIC_IDLE, ROS_LIC_BUSY, ROS_LIC_QR, ROS_LIC_DONE, ROS_LIC_ERROR } ros_license_state_t;bool ros_license_active(void);
bool ros_license_configured(void); /* this firmware has the public key (CONFIG_ROS_LICENSE_PUBKEY) */
bool ros_license_online_possible(void); /* it can be paid for on the device: a license server
* (CONFIG_ROS_LICENSE_SERVER), or its own Ksher account */
bool ros_license_direct(void); /* paying goes straight to Ksher (no license server) */
const char *ros_license_device_id(void); /* "RLD-" + the factory MAC: what a license is made for */
const char *ros_license_info(void); /* "Activated 2026-10-05" / "Free version ..." */
const char *ros_license_lock_info(void); /* what an activation is locked to: "MAC ... + chip ID ..." */
void ros_license_watermark(void); /* LVGL: shows / removes the watermark to match */Online, on its own task: order + QR + waiting for the payment, or (restore) the license of a device that paid before / with Ksher direct: asking about the order made before. The state is read with ros_license_online() (LVGL timer).
ros_license_state_t ros_license_online(char *msg, size_t mn, char *qr, size_t qn, uint32_t *qr_gen, char *amount,
size_t an, int *secs_left);In ros.h for the firmware itself, not exported to apps: ros_license_init, ros_license_ksher_import_sd, ros_license_install, ros_license_refusal, ros_license_import_sd, ros_license_online_start, ros_license_online_stop, ros_license_dialog.
#System log
All ESP_LOG output is also kept in a 64 KB PSRAM ring (viewer: Files -> Log).
void ros_log_init(void);
uint32_t ros_log_head(void); /* total bytes logged since boot */
size_t ros_log_read(uint32_t *pos, char *out, size_t max); /* from *pos (clamped to oldest), advances it */#Time
esp_err_t ros_time_sync_now(void); /* (re)start SNTP with ntp_server now; ESP_ERR_INVALID_STATE: no network */
bool ros_time_valid(void); /* true once SNTP has synced */
void ros_time_sync_start(void); /* start SNTP once any interface is online */#Ethernet
typedef enum {
ROS_ETH_UNAVAILABLE, /* driver/PHY failed to start */
ROS_ETH_NO_LINK, /* cable unplugged */
ROS_ETH_LINK_UP, /* link up, waiting for DHCP */
ROS_ETH_CONNECTED, /* has an IP address */
} ros_eth_state_t;typedef struct {
ros_eth_state_t state;
int speed_mbps;
bool full_duplex;
uint8_t mac[6];
char ip[16], gateway[16], netmask[16], dns[16];
} ros_eth_info_t;esp_err_t ros_eth_start(void);
ros_eth_state_t ros_eth_state(void);
void ros_eth_info(ros_eth_info_t *out);Apply ros_settings()->eth now (no reboot): static address, or back to DHCP. ESP_ERR_INVALID_ARG if the addresses don't parse.
esp_err_t ros_eth_apply_ip(void);#Camera
Called on the camera task with each preview frame: w*h pixels in cf (RGB888 = the display's own format, drawn by LVGL without per-pixel conversion; RGB565 from sources that can't give RGB888)
typedef void (*ros_camera_frame_cb_t)(const void *pixels, int w, int h, lv_color_format_t cf, void *user);esp_err_t ros_camera_start(int preview_w, int preview_h, ros_camera_frame_cb_t cb, void *user);
void ros_camera_stop(void);
bool ros_camera_running(void);
void ros_camera_snapshot(void); /* next full-res frame is saved to SD as BMP */
void ros_camera_set_mirror(bool on);
float ros_camera_fps(void);Overlay: frames go by PPA straight into the display frame buffers at this screen box (no CPU, no LVGL) - only while nothing is drawn on top of it. LVGL context.
void ros_camera_set_overlay(bool on, int x, int y, int w, int h, int radius, uint32_t outside_color);
bool ros_camera_overlay_active(void);
void ros_camera_preview_size(int *w, int *h); /* the scaled picture, once started */#USB host
High-speed USB-C port (always powered). One USB Host Library, four class drivers: MSC (FAT at ROS_USB_MOUNT), HID (keyboard -> LVGL keypad + default group, mouse -> pointer with cursor), VCP (CH34x / CP210x / FTDI / CDC-ACM), UVC (MJPEG webcams).
#define ROS_USB_MOUNT "/usb"typedef enum {
ROS_USB_MSC, ROS_USB_KEYBOARD, ROS_USB_MOUSE, ROS_USB_HID, ROS_USB_SERIAL, ROS_USB_CAMERA,
ROS_USB_SMARTCARD, ROS_USB_PRINTER,
} ros_usb_kind_t;typedef struct {
ros_usb_kind_t kind;
uint8_t addr;
uint16_t vid, pid;
char name[48];
} ros_usb_dev_t;esp_err_t ros_usb_start(void);
int ros_usb_devices(ros_usb_dev_t *out, int max);
void ros_usb_list_add(ros_usb_kind_t kind, uint8_t addr, uint16_t vid, uint16_t pid, const char *name); /* class drivers */
void ros_usb_list_remove(ros_usb_kind_t kind, uint8_t addr);USB smart-card reader (CCID, what PC/SC uses) - ros_ccid.c. Blocking calls: worker tasks only.
typedef enum { ROS_SC_NO_READER, ROS_SC_NO_CARD, ROS_SC_CARD_PRESENT, ROS_SC_CARD_ACTIVE } ros_sc_state_t;void ros_ccid_start(void);
ros_sc_state_t ros_sc_state(void);
uint32_t ros_sc_generation(void); /* changes on reader / card events */
const char *ros_sc_reader_name(void);
const char *ros_sc_info(void); /* exchange level + card protocol */
esp_err_t ros_sc_power_on(uint8_t *atr, size_t *atr_len);
esp_err_t ros_sc_power_off(void);
esp_err_t ros_sc_transmit(const uint8_t *apdu, size_t len, uint8_t *resp, size_t *resp_len); /* resp ends with SW1 SW2 */USB printer (printer class 0x07) - ros_printer.c. One job at a time, printed by its own task.
typedef enum { ROS_PRN_AUTO, ROS_PRN_ESCPOS, ROS_PRN_PCL, ROS_PRN_PS, ROS_PRN_ZPL, ROS_PRN_TSPL, ROS_PRN_TEXT,
ROS_PRN_LANG_COUNT } ros_prn_lang_t;extern const char *const ros_prn_lang_names; /* dropdown options, in ros_prn_lang_t order */typedef struct {
bool active;
uint32_t id; /* changes with every job */
char name[64];
uint32_t sent, total; /* bytes; total 0 = not known yet */
const char *stage; /* "Sending", "Waiting for the printer", ... */
esp_err_t result; /* of the last finished job */
const char *error; /* short reason when result != ESP_OK */
} ros_prn_job_t;void ros_printer_start(void);
bool ros_printer_present(void);
uint32_t ros_printer_generation(void); /* printer attach / detach / status / job changes */
const char *ros_printer_name(void);
const char *ros_printer_device_id(void); /* IEEE 1284 ID string, "" if none */
ros_prn_lang_t ros_printer_lang(void); /* in use: the setting, or detected when AUTO */
int ros_printer_dots(void); /* receipt / label printers: dots per line in use */
const char *ros_printer_status_text(void); /* "Ready", "Out of paper", "Offline", "Error", "" */
bool ros_printer_can_print(const char *path); /* file type this printer can take */
esp_err_t ros_printer_print_file(const char *path);
esp_err_t ros_printer_print_text(const char *text);
esp_err_t ros_printer_test_page(void);
void ros_printer_cancel(void);
void ros_printer_job(ros_prn_job_t *out);Smart card on plain GPIOs (ros_scgpio.c): ISO 7816 T=0, no reader chip, 3.3 V cards only. The pins are the board's: ROS_SCG_PIN_* in ros_board.h.
#define ROS_SCG_VCC_ACTIVE_LOW 0 /* 1 for a P-MOSFET high-side switch (gate low = on) */
#define ROS_SCG_UART 2 /* UART_NUM_2 */
#define ROS_SCG_LEDC_TIMER 2 /* backlight uses timer 1 / channel 1 */
#define ROS_SCG_LEDC_CHANNEL 2bool ros_scg_present(void); /* card-detect switch closed */
esp_err_t ros_scg_power_on(uint8_t *atr, size_t *atr_len);
void ros_scg_power_off(void);
esp_err_t ros_scg_transmit(const uint8_t *apdu, size_t len, uint8_t *resp, size_t *resp_len);Thai national ID card (ros_thid.c) - over the USB reader or the direct GPIO socket
typedef struct {
char cid[24]; /* 1-2345-67890-12-3 */
char name_th[200], name_en[200];
char birth_th[48], birth_en[48];
char gender_th[16], gender_en[16];
char address[400];
char issuer[200];
char card_no[24];
char issue_th[48], expiry_th[48];
uint8_t *photo; /* JPEG, PSRAM (free()), NULL if not read */
size_t photo_len;
int fields_ok, fields_total;
const char *reader; /* "USB: <name>" / "Direct GPIO" */
} ros_thid_t;typedef enum { ROS_THID_NONE, ROS_THID_USB, ROS_THID_GPIO } ros_thid_port_t;ros_thid_port_t ros_thid_card_port(void); /* where a card is inserted now (USB first) */Reads every field; progress(stage, user) is called between fields (from this task). Worker task only - a full read with the photo takes a few seconds.
esp_err_t ros_thid_read(ros_thid_port_t port, ros_thid_t *out, void (*progress)(const char *stage, void *user),
void *user);
void ros_thid_free(ros_thid_t *t); /* photo buffer; wipes the fields */Identification only: 13 digits + Thai name, under a second. Worker task.
esp_err_t ros_thid_read_id(ros_thid_port_t port, char cid[14], char *name_th, size_t name_n);
bool ros_thid_number_valid(const char *digits13); /* check digit of a citizen number */
uint32_t ros_usb_generation(void); /* changes whenever a device comes or goes */
const char *ros_usb_kind_name(ros_usb_kind_t k);
void ros_usb_ui_tick(void); /* LVGL context: mouse cursor visibility */bool ros_usb_msc_mounted(void);
uint64_t ros_usb_msc_total_bytes(void);
uint64_t ros_usb_msc_free_bytes(void);bool ros_usb_vcp_ready(void);
const char *ros_usb_vcp_name(void);
esp_err_t ros_usb_vcp_set_baud(uint32_t baud);
uint32_t ros_usb_vcp_baud(void);
esp_err_t ros_usb_vcp_write(const void *data, size_t len);
size_t ros_usb_vcp_read(void *buf, size_t max); /* non-blocking */Keyboard-style scanners (QR / barcode): characters are collected until Enter
const char *ros_usb_last_scan(void);
uint32_t ros_usb_scan_count(void);
int ros_usb_active_port(void); /* 0 = USB Native, 1 = USB_OTG */bool ros_usb_uvc_present(void);
esp_err_t ros_usb_uvc_start(int w, int h, ros_camera_frame_cb_t cb, void *user);
void ros_usb_uvc_stop(void);
float ros_usb_uvc_fps(void);In ros.h for the firmware itself, not exported to apps: ros_printer_detected_lang, ros_scg_active, ros_scg_info.
#Everything else an app can call
Besides ros.h, the firmware exports 340 names of LVGL 9.2.2, the C library, FreeRTOS and ESP-IDF - the ones the firmware itself uses. An app that calls a name not in reloados/api.txt is refused by build.sh, and by the device. Need one that is missing? Ask Reloader: the next firmware can export it.
LVGL (262)
lv_anim_init lv_anim_set_completed_cb lv_anim_set_delay lv_anim_set_duration lv_anim_set_exec_cb lv_anim_set_values lv_anim_set_var lv_anim_start lv_area_get_height lv_area_get_width lv_async_call lv_bar_create lv_bar_set_range lv_bar_set_value lv_button_create lv_buttonmatrix_clear_button_ctrl lv_buttonmatrix_create lv_buttonmatrix_get_button_text lv_buttonmatrix_get_selected_button lv_buttonmatrix_set_button_ctrl lv_buttonmatrix_set_button_ctrl_all lv_buttonmatrix_set_map lv_chart_add_series lv_chart_create lv_chart_set_all_value lv_chart_set_div_line_count lv_chart_set_next_value lv_chart_set_point_count lv_chart_set_range lv_chart_set_type lv_chart_set_update_mode lv_checkbox_create lv_checkbox_set_text lv_color_black lv_color_darken lv_color_format_get_size lv_color_hex lv_color_make lv_color_mix lv_color_to_u32 lv_color_white lv_display_add_event_cb lv_display_get_buf_active lv_display_get_default lv_display_get_inactive_time lv_display_get_rotation lv_display_remove_event_cb_with_user_data lv_display_set_theme lv_display_trigger_activity lv_draw_buf_destroy lv_draw_buf_width_to_stride lv_draw_rect lv_draw_rect_dsc_init lv_dropdown_add_option lv_dropdown_clear_options lv_dropdown_create lv_dropdown_get_selected lv_dropdown_set_options lv_dropdown_set_selected lv_event_get_code lv_event_get_current_target lv_event_get_layer lv_event_get_target lv_event_get_user_data lv_free_core lv_group_create lv_group_remove_obj lv_group_set_default lv_image_cache_drop lv_image_create lv_image_set_inner_align lv_image_set_scale lv_image_set_src lv_indev_active lv_indev_add_event_cb lv_indev_create lv_indev_get_next lv_indev_get_point lv_indev_get_type lv_indev_set_cursor lv_indev_set_display lv_indev_set_group lv_indev_set_read_cb lv_indev_set_type lv_keyboard_create lv_keyboard_get_textarea lv_keyboard_set_map lv_keyboard_set_mode lv_keyboard_set_popovers lv_keyboard_set_textarea lv_label_create lv_label_get_text lv_label_set_long_mode lv_label_set_text lv_label_set_text_fmt lv_label_set_text_static lv_layer_sys lv_layer_top lv_list_add_button lv_list_create lv_list_get_button_text lv_malloc_core lv_mem_deinit lv_mem_init lv_msgbox_add_close_button lv_msgbox_add_footer_button lv_msgbox_add_text lv_msgbox_add_title lv_msgbox_close lv_msgbox_create lv_obj_add_event_cb lv_obj_add_flag lv_obj_add_state lv_obj_align lv_obj_center lv_obj_clean lv_obj_create lv_obj_delete lv_obj_delete_async lv_obj_fade_in lv_obj_get_child lv_obj_get_child_count lv_obj_get_content_coords lv_obj_get_content_height lv_obj_get_content_width lv_obj_get_coords lv_obj_get_height lv_obj_get_index lv_obj_get_parent lv_obj_get_screen lv_obj_get_scroll_bottom lv_obj_get_scroll_y lv_obj_get_user_data lv_obj_get_width lv_obj_has_flag lv_obj_has_state lv_obj_invalidate lv_obj_invalidate_area lv_obj_is_visible lv_obj_move_to_index lv_obj_remove_event_cb_with_user_data lv_obj_remove_flag lv_obj_remove_state lv_obj_remove_style_all lv_obj_scroll_by_bounded lv_obj_scroll_to lv_obj_scroll_to_view lv_obj_scroll_to_view_recursive lv_obj_scroll_to_y lv_obj_set_ext_click_area lv_obj_set_flex_align lv_obj_set_flex_flow lv_obj_set_flex_grow lv_obj_set_height lv_obj_set_pos lv_obj_set_scroll_dir lv_obj_set_size lv_obj_set_state lv_obj_set_style_arc_color lv_obj_set_style_arc_width lv_obj_set_style_bg_color lv_obj_set_style_bg_grad_color lv_obj_set_style_bg_grad_dir lv_obj_set_style_bg_opa lv_obj_set_style_border_color lv_obj_set_style_border_opa lv_obj_set_style_border_side lv_obj_set_style_border_width lv_obj_set_style_clip_corner lv_obj_set_style_color_filter_opa lv_obj_set_style_image_opa lv_obj_set_style_image_recolor lv_obj_set_style_image_recolor_opa lv_obj_set_style_line_color lv_obj_set_style_line_width lv_obj_set_style_margin_bottom lv_obj_set_style_margin_left lv_obj_set_style_margin_right lv_obj_set_style_margin_top lv_obj_set_style_max_height lv_obj_set_style_min_height lv_obj_set_style_min_width lv_obj_set_style_opa lv_obj_set_style_pad_bottom lv_obj_set_style_pad_column lv_obj_set_style_pad_left lv_obj_set_style_pad_right lv_obj_set_style_pad_row lv_obj_set_style_pad_top lv_obj_set_style_radius lv_obj_set_style_shadow_color lv_obj_set_style_shadow_offset_y lv_obj_set_style_shadow_opa lv_obj_set_style_shadow_width lv_obj_set_style_text_align lv_obj_set_style_text_color lv_obj_set_style_text_font lv_obj_set_style_text_letter_space lv_obj_set_style_text_line_space lv_obj_set_style_text_opa lv_obj_set_style_transform_pivot_x lv_obj_set_style_transform_pivot_y lv_obj_set_user_data lv_obj_set_width lv_obj_update_flag lv_obj_update_layout lv_pct lv_qrcode_create lv_qrcode_set_dark_color lv_qrcode_set_light_color lv_qrcode_set_size lv_qrcode_update lv_realloc_core lv_roller_create lv_roller_get_selected lv_roller_set_options lv_roller_set_selected lv_roller_set_visible_row_count lv_screen_active lv_screen_load_anim lv_slider_create lv_slider_get_value lv_slider_set_range lv_slider_set_value lv_spinner_create lv_switch_create lv_table_create lv_table_set_cell_value lv_table_set_cell_value_fmt lv_table_set_column_count lv_table_set_column_width lv_table_set_row_count lv_tabview_add_tab lv_tabview_create lv_tabview_get_tab_active lv_tabview_get_tab_bar lv_tabview_set_tab_bar_size lv_text_get_width lv_textarea_add_text lv_textarea_create lv_textarea_delete_char lv_textarea_get_label lv_textarea_get_text lv_textarea_set_accepted_chars lv_textarea_set_cursor_click_pos lv_textarea_set_cursor_pos lv_textarea_set_max_length lv_textarea_set_one_line lv_textarea_set_password_mode lv_textarea_set_placeholder_text lv_textarea_set_text lv_theme_default_init lv_tick_elaps lv_tick_get lv_timer_create lv_timer_delete lv_timer_get_user_data lv_timer_pause lv_timer_reset lv_timer_resume lv_timer_set_period lv_timer_set_repeat_count
Fonts (13)
lv_font_get_line_height lv_font_montserrat_12 lv_font_montserrat_14 lv_font_montserrat_16 lv_font_montserrat_20 lv_font_montserrat_24 lv_font_montserrat_28 lv_font_montserrat_32 lv_font_montserrat_40 lv_font_montserrat_48 rld_font_thai_30 rld_font_thai_bold_40 rld_font_thai_bold_56
FreeRTOS (15)
vQueueDelete vStreamBufferDelete vTaskDelay xQueueCreateMutex xQueueGenericCreate xQueueGenericReset xQueueGenericSend xQueueReceive xQueueSemaphoreTake xStreamBufferGenericCreateStatic xStreamBufferReceive xStreamBufferReset xStreamBufferSend xTaskCreatePinnedToCore xTaskCreatePinnedToCoreWithCaps
ESP-IDF (18)
esp_log esp_log_timestamp esp_timer_get_time gpio_pullup_en heap_caps_malloc nvs_close nvs_commit nvs_get_i32 nvs_get_str nvs_open nvs_set_i32 nvs_set_str uart_driver_delete uart_driver_install uart_param_config uart_read_bytes uart_set_baudrate uart_set_pin
C library (29)
atoi fclose fgets fopen fprintf free fwrite localtime_r lodepng_decode32 malloc memchr memcpy memmove memset mkdir remove rename ros_scr_w snprintf stat strchr strcmp strftime strlcpy strlen strncmp strspn strstr time
Embedded files (2)
_binary_lan_png_end _binary_lan_png_start
Compiler runtime (1)
__divdi3