Repository navigation
Release Highlights
This major update introduces comprehensive LilyGO T-Deck Plus support, a new on-device AI image generation engine, complete Bluetooth and GPS subsystems, expanded JavaScript APIs, native audio playback, enhanced image rendering, secure MicroSD backup and disaster recovery, improved hardware integration, performance optimizations, and numerous bug fixes.
Added
-
LilyGo T-Deck Plus Hardware Profile (
lilygo-t-deck):- Full dedicated board abstraction layer in
src/Hal/Boards/t_deck/(BoardConfig.h,BoardConfig.cpp) and modular PlatformIO environment configurationsrc/Hal/Boards/board_configs/t_deck.ini. - ST7789 IPS LCD (
$320 \times 240$ ) SPI driver with custom backlight PWM control on GPIO 42, configured to upright handheld orientation (rotation 1) matching the device form factor. - Goodix GT911 capacitive touch screen support on I2C (
0x5D/0x14, INT GPIO 16) with direct coordinate mapping, 4-corner touch calibration, and LittleFS calibration persistence. - ESP32-C3 QWERTY physical keyboard driver communicating over shared I2C (
0x55) with interrupt monitoring on GPIO 46, backlight control, and character/modifier decoding. - 5-Way trackball navigation integration (GPIO 3, 15, 2, 1, 0) mapped to
BOARD_KEY_UP,BOARD_KEY_DOWN,BOARD_KEY_LEFT,BOARD_KEY_RIGHT, andBOARD_KEY_ENTER. - MicroSD card storage mounting on shared SPI bus with dedicated CS GPIO 39 and electrical LoRa chip-select isolation on GPIO 9.
- Accurate 8-point piecewise linear battery gauge & charging telemetry on GPIO 4.
- Active peripheral power gate sequence asserting
BOARD_POWERON(GPIO 10) high on hardware init. - Official
"lilygo-t-deck"target added to release and OTA update workflows (.github/workflows/release.yml,.github/workflows/push-update.yml,updates/esp32/v2/update.json).
- Full dedicated board abstraction layer in
-
On-Device 4.0M Neural Image Generation Engine (
ImageRunner,AIEngine,LocalAI):- Engineered genuine neural network forward inference in
src/LocalAI/Runners/ImageRunner.cppexecuting all 4,003,683 INT8 parameters ofkryonimage_3m_96_800.krai(DCGAN-96). - 5-Layer deep convolutional pipeline:
init_projLinear(128, 18432) + Folded BatchNorm1d + ReLU -> 4 stages of fused 2x nearest-neighbor upsampling + Conv2d + Folded BatchNorm2d + ReLU -> Conv2d Head + Tanh -> direct RGB565 SPI DMA display blit. - Zero-heap allocation during forward inference: pre-allocated PSRAM ping-pong buffers (
m_actBuf0= 1.18 MB,m_actBuf1= 589 KB) and 2D upsampling cache plane (m_upPlane= 36.8 KB). - Pre-folded BatchNorm optimization folding gamma, beta, mean, variance into effective per-channel scale and bias multipliers during model initialization.
- FreeRTOS cooperative scheduling with periodic watchdog delays (
vTaskDelay(1)) preventing Task Watchdog timeouts while keeping the UI and Duktape runtime at 60 FPS on Core 0. - Numerical accuracy verified against PyTorch reference with
$\le 1$ LSB rounding tolerance.
- Engineered genuine neural network forward inference in
-
Global GPS Subsystem & Location Services (LilyGO T-Deck Plus GNSS,
GPSEngine,GPSGlobal Object):- Hardware UART driver on GPIO 44 (RX) and GPIO 43 (TX) with 4096-byte ring buffer and peripheral power rail management on GPIO 10 (
BOARD_POWERON). - Kernel-only in-RAM auto-baud negotiation and hardware chipset auto-identification: probes
38400(u-blox MIA-M10Q default),9600(Quectel L76K / AT6558R default), and115200baud with LittleFS baud persistence (/local/system/gps_settings.json). - Dual-layer NMEA decoding engine on Core 0 combining
TinyGPSPluswith a direct checksum-verified multi-constellation NMEA parser supporting all talker prefixes (GP,GN,BD,GB,GL,GA,QZ) and sentence types (RMC,GGA,GNS,GLL,GSA,GSV,VTG). - Live RF carrier signal telemetry: per-satellite SNR (C/N0), visible satellites count, carrier locks, and average SNR to monitor cold ephemeris downloads.
- Native KryonOS Permission Manager gating (
"location"permission) backed by/local/system/app_permissions.jsonwith a 3-choice modal dialog ("Allow Once", "Always Allow", "Deny"). - Offline satellite atomic clock synchronization via
GPS.getTime()andGPS.syncSystemTime()calibrating the ESP32 system clock and PCF8563 RTC. - High-precision native C++ geodesy engine:
GPS.distanceBetween(Haversine),GPS.courseTo(bearing), andGPS.isInsideCircle(geofence radial boundary). - Complete Duktape JavaScript bindings for global
GPSobject:isAvailable(),isEnabled(),start(),stop(),enable(),disable(),hasFix(),getStatus(),getLocation(),getLastKnownLocation(),getTime(),syncSystemTime(),watchPosition(),clearWatch(),distanceBetween(),courseTo(),isInsideCircle(),setRate(),getBaud(), andrequestPermission(). - Dedicated GPS Settings UI screen (
STATE_SETTINGS_GPS = 24) inside the Connections menu.
- Hardware UART driver on GPIO 44 (RX) and GPIO 43 (TX) with 4096-byte ring buffer and peripheral power rail management on GPIO 10 (
-
Complete Bluetooth Subsystem & Duktape JavaScript Bindings (
BluetoothEngine,Bluetooth):- Central hardware abstraction layer in
src/Hal/Bluetooth/BluetoothEngine.cppexposing globalBluetoothobject in Duktape JavaScript engine (src/Runtime/JSBindings_Bluetooth.cpp). -
BLE Central Scanner & Beacon Utilities: Asynchronous LE scanner with Core 0 zero-heap circular duplicate debounce cache, thread-safe ring buffer queue, and native Apple iBeacon & Google Eddystone-URL packet parsers (
Bluetooth.BLE.Scanner,Bluetooth.Utils.parseBeacon). -
BLE Central GATT Client: Asynchronous Promise-based GATT client (
Bluetooth.BLE.connect) supporting service/characteristic discovery, MTU negotiation (up to 512 bytes), characteristic read/write, descriptor access, and live notification subscriptions (GattCharacteristic.startNotifications). -
BLE Peripheral Local GATT Server & GAP Broadcaster: Host local GATT services (
Bluetooth.BLE.Server.createService) and broadcast standard or extended advertising payloads up to 251 bytes (Bluetooth.BLE.Advertiser). -
BLE HID Wireless Keyboard Host (HOGP): Standard USB HID report descriptor with Just Works BLE bonding, turning KryonOS devices into wireless Bluetooth keyboards for smartphones and PCs (
Bluetooth.BLE.Keyboard). -
Dedicated Bluetooth Settings Screen (
STATE_SETTINGS_BLUETOOTH 22): Non-destructive runtime power toggle, local GAP name, MAC address, and silicon architecture badges.
- Central hardware abstraction layer in
-
Native MP3 Audio Playback Engine (
AudioEngine,minimp3):- Embedded high-performance
minimp3fixed-point decoder directly into the OS audio subsystem (src/Hal/Audio/minimp3.h), delivering hardware-accelerated MP3 decoding on ESP32-S3 Core 0. - Streaming playback support from both Internal Flash (
/local) and MicroSD Card (/sd), plus in-memory raw buffer decoding (playMp3Memory). - ID3v2 metadata skip parser: inspects 10-byte ID3v2 headers, calculates syncsafe integer tag sizes, and seeks past embedded album art and metadata (100 KB–500 KB) to eliminate digital static.
- 32 KB PSRAM stream ring buffer insulating audio decode tasks from SD card SPI latency spikes and background file system operations.
- Unified playback API (
Audio.play/Speaker.play) with intelligent magic byte header inspection (RIFFvsID3/sync word0xFFE0) for seamless format auto-detection. - Complete Duktape JavaScript bindings across
Speaker,Audio, andSystem.speaker:playMp3(path),play(path), andseek(positionMs).
- Embedded high-performance
-
Global High-Performance Image Rendering Subsystem (
ImageRenderer,TJpg_Decoder,PNGdec):- Unified image rendering pipeline supporting PNG, JPEG, and BMP formats across Internal Flash (
/local) and MicroSD (/sd). - Native PNG decoding with full 8-bit alpha channel transparency blending (
blendRGB565) and 1-bit palette transparency masking on ESP32-S3 SIMD instructions. - Hardware-accelerated JPEG decoding with 16x16 MCU block streaming and automatic downscaling factors (1x, 2x, 4x, 8x) for rendering multi-megapixel images in limited RAM.
- Pre-flight image inspection API (
getImageInfo): queries dimensions, color depth, format, and alpha transparency without decompressing full image payloads into RAM. - Dual rendering destination support: seamlessly renders to active double-buffer sprites (
JSBindings::getActiveSprite()) or directly to the TFT glass. - Global JavaScript bindings:
Display.drawImage(path, x, y, [options]),Display.drawPNG(),Display.drawJPG(),Display.drawBMP(), andDisplay.getImageInfo().
- Unified image rendering pipeline supporting PNG, JPEG, and BMP formats across Internal Flash (
-
Advanced File System (FS) JavaScript APIs (
FS.readChunk,FS.readBinary,FS.writeBinary,FS.copyFile,FS.stat,FS.isSDMounted,FS.rmdir):-
Chunked File Slicing (
FS.readChunk(path, offset, length, [asBinary])): Streams arbitrary byte ranges without loading the whole file into RAM, with 16 KB allocation ceiling and seek validation. -
High-Performance Binary I/O (
FS.readBinary(path),FS.writeBinary(path, buf)): Direct TypedArray asset loading intoUint8Arrayfor sprites, audio samples, and fonts. -
Cross-Partition File Copying (
FS.copyFile(src, dst)): High-speed 4 KB heap-buffered stream copy between Internal Flash (/local) and MicroSD (/sd) with anti-self-copy protection and ENOSPC rollback. -
Atomic Metadata Lookups (
FS.stat(path)): Returns{ size, isDirectory, isFile, exists, mtime, drive }in a single native call. -
Hardware Media Guard & Concurrency: Instant non-blocking
FS.isSDMounted()check and FreeRTOS recursive mutex (FileSystem::lock(),FSLockGuard) isolating Core 0 audio/BLE tasks from Core 1 file I/O.
-
Chunked File Slicing (
-
Secure MicroSD Card Backup & Disaster Recovery Subsystem (
BackupManager,SettingsUI):- Full atomic backup of internal LittleFS storage (
/local) to external MicroSD (/sd/backups/kryon_backup_<date>.kbf). - Cryptographically hardened security model deriving dedicated 256-bit subkeys
$K_{\text{enc}}$ (AES-256-CBC) and$K_{\text{mac}}$ (HMAC-SHA256) via domain-separated labels. - Hardware-accelerated encryption for all
/system/configuration files (WiFi credentials, display/keyboard settings, time configurations, touch calibrations, permissions) using unique per-file random 16-byte IVs from silicon TRNG. - Dual-Key Disaster Recovery: Quick Backup (Device-Locked via silicon eFuse MAC registers) and Portable Backup (Passphrase-Protected via PBKDF2-HMAC-SHA256).
- Multi-archive catalog browser with timestamp sorting,
[ LATEST ]badge,</>carousel selector, interactive deletion confirmation, and on-screen keyboard passphrase prompts.
- Full atomic backup of internal LittleFS storage (
-
Extensible "Our Sponsors" Showcase & Dynamic QR Code Modal (
SettingsUI,SponsorAssets.h):- Added an "Our Sponsors" button in Settings -> About Device supporting both landscape (
$320 \times 240$ ) and portrait ($240 \times 320$ ) layouts. - Added the Our Sponsors screen showcasing official hardware partner with a crisp
$166 \times 50$ RGB565PROGMEMlogo alongside a "Want to support?" community banner (https://kryonos.harislab.tech/sponsor). - Built a data-driven
SPONSOR_LIST[]registry (SponsorEntrystruct insrc/Settings/SponsorAssets.h) with automatic</>pagination controls and(1/N)header badge when multiple sponsors are registered. - Engineered an on-device runtime ISO/IEC 18004 QR code generator (
MiniQRnamespace, Versions 1–5, ECC Level L) that dynamically encodes any sponsor or support URL into a scannable QR code modal (< Back+ Sponsor title + QR matrix + URL +[ Scan with phone camera ]) with zero heap allocations. - Added
tools/logo_to_rgb565.pyCLI utility to convert transparent PNG sponsor logos into anti-aliased RGB565PROGMEMarrays blended against the KryonOS card surface (0x10A2).
- Added an "Our Sponsors" button in Settings -> About Device supporting both landscape (
-
Hardware & Device-Specific JavaScript APIs (
Trackball,Keyboard,Speaker,Device):-
Trackball/System.trackball:getState(),getDelta(),isClicked(),isPressed(),getRawCounts(), andreset(). -
Keyboard/System.keyboard:getKey(),isPressed(),getModifiers(),setBacklightLevel(),getBacklightLevel(), andclear(). -
Speaker/Audio/System.speaker: Asynchronous WAV streaming on Core 0 (playWav,playWavMemory), procedural tone synthesis (playTone), melody engine (playMelody), and built-in preset beeps (playBeep). -
Device/System.device: Hardware discovery flags (hasTrackball,hasKeyboard,hasSpeaker,hasTouch,hasBattery), battery SoC telemetry (getBatteryPercent,getBatteryVoltage,isCharging,getChargeTimeRemaining,getDischargeTimeRemaining), and display backlight control (setBrightness,getBrightness).
-
-
Responsive Display Framework & Dynamic Screen Geometry:
- Eliminated all fixed 240x320 hardcoded dimensions across all OS UI subsystems (
LauncherUI,SettingsUI,AppStoreUI,InstallerUI,HelpCenterUI,WebServerAppUI,KryonCloudUI,MyKeyboard). - Dynamic display dimension calculation (
tft.width(),tft.height()) supporting both wide landscape displays ($320 \times 240$ on LilyGo T-Deck Plus) and vertical portrait displays ($240 \times 320$ ) with full screen utilization. - Implemented responsive 2-column layouts for Settings, WiFi Options, Time & Region, and About Device on displays with vertical height
$< 280\text{px}$ . - Unified system header bar (
drawSystemTopBar) with dynamic title clipping, live 4-bar WiFi RSSI signal strength monitoring, and precision battery gauge with charging bolt. - Automatic display sleep state machine smoothly turning off backlight on inactivity and waking instantly on touch, trackball, or key inputs.
- Eliminated all fixed 240x320 hardcoded dimensions across all OS UI subsystems (
-
System Settings Expansion:
- Re-architected main Settings menu with a top-level
"Connections"hub (STATE_SETTINGS_CONNECTIONS 21) routing to WiFi Options, Bluetooth Options, and GPS Settings. - Added Display Settings (
STATE_SETTINGS_DISPLAY 18): Backlight brightness levels and sleep timeout presets. - Added Keyboard Settings (
STATE_SETTINGS_KEYBOARD 19): Backlight intensity presets and physical typing preview. - Added Battery & Power Settings (
STATE_SETTINGS_BATTERY 20): Live SoC gauge, 16-sample oversampled voltage curve, and charge/discharge runtime estimates.
- Re-architected main Settings menu with a top-level
JavaScript Apps & Examples
-
Universal Automated API Diagnostic Suite (
test/com.kryonos.apitest):- Full-stack automated JavaScript diagnostic test application systematically validating 15 native KryonOS subsystems: System, Device Telemetry, Filesystem, Hardware Cryptography, Hardware Inputs (Keyboard/Trackball/Touch), Audio, Graphics primitives, GPIO, PWM, I2C, Network, GPS, Notifications & IPC, Bluetooth, and Local AI.
- Interactive workbench with live progress bar, microsecond benchmark timing, categorized scrollable test report, hardware keyboard and trackball navigation, and persistent diagnostic report export to
/local/api_test_report.txtand/sd/api_test_report.txt.
-
Neural Image Studio (
test/com.kryonos.imagegen):- Cyberpunk-themed AI image generation application running DCGAN-96 forward inference on-device.
- Features 18 elemental classes (
Normal,Fire,Water,Grass,Electric, etc.), guidance scale & variance sliders,$320 \times 240$ landscape and$240 \times 320$ portrait adaptive layout, double-buffered frame restoration viaSystem.ai.blitFrame(), and hardware trackball/keyboard controls.
-
Concert Grand Piano Handheld Synthesizer (
test/com.kryonos.piano):- Realistic dark polished mahogany fallboard and 3D ivory/ebony keys with sinking depression and glossy bevels.
- High-fidelity procedural audio synthesis via I2S DAC / MAX98357A amplifier with equal-temperament tuning (A4 = 440 Hz), 4 instrument voice presets (Concert Grand, Electric Piano, Harpsichord, Pipe Organ), sustain resonance, and built-in synchronized demo player (Für Elise, Canon in D, Twinkle Twinkle).
-
BLE HID Wireless Keyboard Controller (
test/com.kryonos.blekeyboard):- Turns LilyGO T-Deck Plus and Cardputer into a wireless Bluetooth keyboard for smartphones (iOS / Android) and PCs via BLE HOGP.
- Real-time connection status pill, interactive key chime sound toggle, zero-flicker targeted rendering, live output stream monitor, physical keyboard typing bridge, and 5-way trackball mouse navigation.
-
Audio Player Application v2.0.0 (
test/com.kryonos.musicplayer):- High-fidelity digital audio player supporting both MP3 and WAV playback.
- Native unified audio file picker with multi-format filter (
.mp3,.wav) for Internal Flash and MicroSD, real-time codec badges ([MP3]vs[WAV]), dynamic bitrate duration estimation, asynchronous Core 0 streaming, animated 12-band audio spectrum visualizer, and trackball playlist navigation.
-
Image Viewer & Gallery Application (
test/com.kryonos.imageviewer):- High-performance image browser previewing PNG, JPEG, and BMP images across
/localand/sd. - Pre-flight image inspection panel (dimensions, file size, format badge, alpha channel), full-screen rendering, interactive zoom (Fit-to-Screen, 1x, 2x, 4x, 8x hardware downscaling), trackball/touch viewport panning, and automated slideshow mode.
- High-performance image browser previewing PNG, JPEG, and BMP images across
-
Bluetooth Inspector Diagnostics Suite (
test/com.kryonos.bttest):- 5-Tab Bluetooth diagnostics utility: Tab 1 Radar (nearby BLE scanner with RSSI bars and iBeacon/Eddystone badges), Tab 2 Inspector (GATT client explorer with 512 MTU and notification streaming), Tab 3 Host (local GATT server hosting Device Information Service
180A), Tab 4 NUS Terminal (Nordic UART Service console), and Tab 5 Radio Telemetry (power toggle and MAC info).
- 5-Tab Bluetooth diagnostics utility: Tab 1 Radar (nearby BLE scanner with RSSI bars and iBeacon/Eddystone badges), Tab 2 Inspector (GATT client explorer with 512 MTU and notification streaming), Tab 3 Host (local GATT server hosting Device Information Service
-
GNSS Satellite & Location Workbench (
test/com.kryonos.gpstest):- Real-time satellite constellation monitor displaying satellites in view, active carrier signal locks, per-satellite SNR (C/N0) signal bars, cold ephemeris download timer, 3D fix coordinates, speed/altitude telemetry, and atomic RTC clock synchronization.
-
File System Inspector & Diagnostic Lab (
test/com.kryonos.fstest):- Automated diagnostic utility verifying all 6 new FS JavaScript APIs (
FS.readChunk,FS.readBinary,FS.writeBinary,FS.copyFile,FS.stat,FS.rmdir) with PASS/FAIL badges, live 64-byte block chunk inspector, and storage space visualizers.
- Automated diagnostic utility verifying all 6 new FS JavaScript APIs (
-
T-Deck Plus Hardware Diagnostics Lab (
test/com.kryonos.tdecktest):- Multi-tab hardware testing utility for LilyGO T-Deck Plus verifying trackball directional counts, keyboard matrix keys, audio amplifier volume sliders, and double-buffered display rendering without screen flicker.
Changed
- Standardized active hardware environments on primary ESP32-S3 targets: added
lilygo-t-deckacross build, release, and OTA pipelines, settingdefault_envs = lilygo-t-deckinplatformio.ini. - Updated the Device Credentials Guide on the Web Server login page (
src/WebManager/WebManager.cpp) and the Web Server app status view (src/WebServerApp/WebServerAppUI.cpp) to reflect the updated settings path: Settings -> Connections -> WiFi Options -> Web Server. - Re-architected main Settings menu to replace the top-level
"WiFi Options"button with a unified"Connections"hub. - Bumped KryonOS version to
3.0.0(-D KRYONOS_VERSION="3.0.0"inplatformio.ini). - Bumped KryonOS API Level to
3(-D KRYONOS_API_LEVEL=3inplatformio.ini).
Removed
- Legacy Board Environments (
esp32-cyd-28,esp32doit-devkit-v1):- Removed legacy Cheap Yellow Display (
esp32-cyd-28) and generic breadboard WROOM (esp32doit-devkit-v1) targets fromplatformio.ini, GitHub Release matrix (.github/workflows/release.yml), and OTA update manifests (.github/workflows/push-update.yml,updates/esp32/v2/update.json) to standardize active development on ESP32-S3 handheld and dev targets.
- Removed legacy Cheap Yellow Display (
Fixed
-
Neural Image Generation Model Loading & Synthesis Fix (
ImageRunner,AIEngine,AIBindings,com.kryonos.imagegen):- Resolved root cause preventing
test/com.kryonos.imagegenfrom synthesizing images despite successfully mountingkryonimage_3m_96_800.krai:ImageRunner::parseTensors()applied a duplicate offset (m_weights + m_header.weights_offset). BecauseAIEngine::loadModel()already loads the weights payload fromweights_offsetintom_modelBuffer, addingweights_offseta second time jumped 240 bytes into the raw weights data, causing tensor name length validation (nlen > 31) to fail and yielding 0 parsed tensors, which causedgenerate()to abort with"required DCGAN tensors missing from .krai model". - Fixed pointer to
const uint8_t* ptr = m_weights;andconst uint8_t* end = ptr + m_header.weights_size;, restoring immediate parsing of all 28 INT8 neural tensors (class_embed,init_proj,up1throughup4, andout_conv). - Added vocabulary table transmission from
AIEnginetoImageRunner::init(m_header, m_modelBuffer, m_vocabBuffer): parses all 18 elemental classes (Normal,Fire,Water,Grass,Electric, etc.) directly from the embedded.kraistring table with safe string length checks and clean fallbacks. - Eliminated FreeRTOS Core 1 Task Watchdog Timer (TWDT) starve panics during deep 4.0M parameter convolution operations: replaced
taskYIELD()(which only yields to tasks of equal or higher priority$\ge 5$ , starving Core 1 IDLE priority 0) with periodicvTaskDelay(pdMS_TO_TICKS(1))every 16 channels inrun_up_block(), every 2048 iterations ininit_proj, after each up-sampling stage, and between output channels inout_conv. - Added guard against negative variance (
if (var < 0.0f) var = 0.0f;) inprecomputeBatchNorm()to preventNaNfloat corruption during BatchNorm parameter folding. - Fixed RGB565 color representation: replaced inverse byte-swapping with native word packing
((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)matchingtft.pushImageexpectations on T-Deck ST7789 display controllers. - Added
System.ai.blitFrame(x, y)API: exposedAIEngine::blitLastFrame(x, y)to Duktape JavaScript runtime, enablingcom.kryonos.imagegento instantly restore and re-blit synthesized sprites when switching tabs or refreshing status cards without re-running synthesis. - Added failure event reporting: queued
AI_EVENT_ERRORinAIEngine::runWorkerwhen image generation cannot proceed, ensuring JavaScriptonErrorcallbacks receive diagnostic error messages.
- Resolved root cause preventing
-
T-Deck Plus GPS Lock & Receiver Engine Fix (
GPSEngine,BoardConfig,com.kryonos.gpstest):- Resolved root cause keeping
test/com.kryonos.gpsteststuck on"Awaiting Fix"with 0 bytes processed under open sky:initHardware()executed a 5 msINPUT_PULLDOWNcheck onBOARD_GPS_RX_PIN(GPIO 44) right at boot before the GNSS module stabilized its internal MCU, falsely settings_isTDeckPlus = falseand disabling GPS availability (hasGPS() = false,isAvailable() = false). - Removed destructive pulldown probe, safely pre-configuring GPS pins with standard idle levels (
INPUT_PULLUPon RX 44,OUTPUT HIGHon TX 43) and keeping GPS available on the T-Deck platform. - Increased auto-baud candidate probing window from 1200 ms to 3500 ms in
GPSEngine::gpsTaskWorker: 1200 ms was chopping 1 Hz (1000 ms) NMEA bursts mid-sentence, preventing valid checksum verifications. - Added baud persistence to LittleFS (
/local/system/gps_settings.json): once locked (38400 for MIA-M10Q, 9600 for L76K), the baud rate is remembered across reboots for instant, zero-delay initialization. - Removed aggressive 15-second baud unlock that dropped baud lock during normal 25-35s cold-sky satellite ephemeris downloads.
- Enhanced sentence validity checks across RMC (
status == 'A'), GGA ($1 \le \text{quality} \le 6$ ), and GLL (status == 'A'). - Implemented multi-constellation GSV sentence accumulation, accurately aggregating satellites in view, active carrier signals, and average SNR across GPS, BeiDou, GLONASS, and Galileo.
- Added periodic flash persistence of valid 3D fixes to
/local/system/gps_last_loc.jsonevery 30 seconds. - Updated
test/com.kryonos.gpstestto provide real-time sky search telemetry (visible satellites, carrier signals, ephemeris download timer) while acquiring fix.
- Resolved root cause keeping
-
App Store Update Hash Resolution & Incompatible API Level Filtering (
AppStoreUI):- Fixed "Installation Blocked: Hash Not Found in store" bug occurring during application updates:
checkUpdates()previously polled remoteapp.jsonwhich does not store package SHA-256 hashes, leavingmetaSha256andappSha256empty and causingperformInstall()to reject updates. - Implemented dynamic, zero-hardcoding category manifest resolution (
deriveCategoryIndexUrl()): dynamically slices{category-name}from anymetaUrlpath (e.g.categories/{category-name}/...->categories/{category-name}/index.json), supporting all categories (Games,Utilities,Multimedia,Demos,System,Tools, etc.) with universal 2-level parent directory traversal. - Added package matching against
categories/{category-name}/index.jsonbypackageName, querying and populatingmeta_sha256andapp_sha256for seamless SHA-256 integrity verification inCryptoEngine. - Added in-session category manifest caching during update checks, preventing redundant network requests when multiple apps belong to the same category.
- Added strict OS API level compatibility filtering (
api <= KRYONOS_API_LEVEL): if an app or update specifies anapilevel higher than the installed system inindex.jsonorapp.json, it is completely hidden from both the App Store category browser and the updates list. - Fixed T-Deck (
$320 \times 240$ ) dialog text misalignment inAppStoreUI::drawDialog(): explicitly setTC_DATUM(Top-Center) andMC_DATUMondrawString(), eliminating horizontal text clipping and adding a centered modal dialog box with OK button matching the touch hit target. - Fixed "No Update found." screen text on T-Deck Plus displays: aligned properly in the screen center using
MC_DATUM(Middle-Center) with a clean two-line layout:"No New Updates Available"and"All Apps Are Up To Date"in accent green.
- Fixed "Installation Blocked: Hash Not Found in store" bug occurring during application updates:
-
On-Device Local AI Garbage Output & T-Deck UI Fix (
com.kryonos.localai,AIEngine):- Resolved root cause of garbage text generation when loading
.binmodels (e.g.kryonai_3m.bin): legacy 24-byte header.binfiles lacked an embedded vocabulary table, and attempting to parse companion 255 KBkryon_tokenizer.jsonfiles on ESP32 exhausted Internal SRAM (malloc()failure in ArduinoJsondeserializeJson), leavingm_vocabBuffernull and forcing an ASCII fallback where all tokens$> 127$ produced blank spaces. - Implemented
SpiRamJsonAllocatorinsrc/LocalAI/AIEngine.cppto stream JSON tokenizer deserialization directly into Octal PSRAM. - Added automatic companion
.kraivocabulary extraction: when loadingkryonai_3m.bin,AIEngineautomatically checks for and extracts pre-baked vocabularies from sibling.kraicontainers. - Packaged all-in-one
kryonai_3m.krai(3.25 MB) with universal 64-byteModelHeader, 4,096 embedded BPE tokens, and 16-byte SIMD-aligned INT8 weights for instantaneous 1 ms loading with zero JSON overhead. - Corrected prompt conditioning in
AIEngine::runWorkerto ensure prompts match the model's trained dialogue format (<|system|>You are KryonAI, the local assistant for KryonOS.<|user|>{prompt}<|assistant|>). - Fixed
test/com.kryonos.localai/main.js: replaced destructiveappendTokenunderscore strip with clean BPE subword and whitespace reconstruction; made UI fully responsive for$320 \times 240$ landscape displays (fixed off-screen tabs and buttons); and added physical T-Deck keyboard and 5-way trackball navigation.
- Resolved root cause of garbage text generation when loading
-
T-Deck Charger Disconnect Chattering Elimination:
- Implemented a 6-second post-disconnect lockout cooldown (
s_lastDisconnectMs) insrc/Hal/Boards/t_deck/BoardConfig.cpp. - Suppressed false re-connection triggers caused by electrochemical relaxation voltage rebound (+20mV to +40mV) after disconnecting USB-C power.
- Increased charging connection debounce confirmation threshold from 1.5 seconds to 3.0 seconds with a mandatory +200mV surge check during lockout.
- Implemented a 6-second post-disconnect lockout cooldown (
-
Time Zone Persistence Across NTP Syncs & Reboots:
- Fixed an issue where setting time zone in Settings (e.g.
UTC+5 PKT$\rightarrow$ UTC-5) failed to persist across reboots or WiFi connections. - In
src/Kernel/TimeManager.cpp, added.trim()sanitization during preference loading and immediately re-asserted POSIXsetenv("TZ", currentTimezone.c_str(), 1)andtzset()right after Arduino-ESP32'sconfigTime(0, 0, ...)(which internally wipedTZback toUTC0).
- Fixed an issue where setting time zone in Settings (e.g.
-
LilyGO T-Deck / T-Deck Plus Dynamic Model Identification:
- Resolved generic
"ESP32-S3"fallback in device identification strings. - Implemented boot-time hardware pulldown probe on
BOARD_GPS_RX_PIN(GPIO 44) to distinguish base"T-Deck"from GPS-equipped"T-Deck Plus". - Integrated active NMEA checksum lock in
GPSEnginecallingsetGpsHardwareConfirmed(true)to lock"T-Deck Plus"once satellite telemetry streams. - Updated
System.getInfo().deviceName,System.getInfo().boardModel,Device.getName(), and the Settings "About Device" UI.
- Resolved generic
-
KryonOS Cloud Responsive UI on T-Deck Plus (320x240 Landscape):
- Completely refactored
src/Kernel/Services/KryonCloud/KryonCloudUI.cppto dynamically adapt to 320x240 landscape displays. - Replaced hardcoded portrait dimensions (240x320) with responsive dual-column grid layouts for Overview and Limits screens.
- Recomputed scroll bounds, button positions, and touch hitboxes for Pairing, AI Console, Beam, and Cloud Storage modals.
- Completely refactored
-
Disaster Recovery Restore Failure (Error Code 10:
BACKUP_ERR_SECURITY_VIOLATION):- Fixed bug during backup restoration where valid backup archives were rejected with
Error Code: 10(BACKUP_ERR_SECURITY_VIOLATION). - Resolved root cause in
BackupManager::isSafePath: the security validator previously rejected any path starting with/or\\(if (path.startsWith("/") || path.startsWith("\\")) return false;). Because LittleFS directory iteration returns canonical absolute paths (file.path()returning"/system/settings.json","/apps/..."), legitimate archive entries were falsely flagged as malicious path traversals. - Re-engineered
BackupManager::isSafePathandrestoreBackupto safely normalize absolute paths by stripping leading slashes and relative dot prefixes (./,.\\) while strictly enforcing genuine directory traversal checks (..path segments,/../,\\..\\), null-byte injection prevention (\0), and drive prefix guards (:). - Enhanced
SettingsUIerror dialogs to display explicit, user-friendly messages for all failure conditions (Security Error,Storage Error,Key Error,Integrity Error,Format Error) rather than ambiguous numeric codes.
- Fixed bug during backup restoration where valid backup archives were rejected with
-
Disaster Recovery Post-Flash-Erase Restore Failure (
Manifest HMAC corrupt! Tampered File.):- Fixed issue in the Secure MicroSD Card Backup & Disaster Recovery Subsystem where a device-locked backup created before a full flash wipe (
esptool.py erase_flash) failed to restore withManifest HMAC corrupt! Tampered File.on the same physical board. - Resolved root cause in
CryptoEngine::getDeviceKey: the device encryption key was previously generated from volatile random bytes (esp_fill_random) and stored in flash NVS (Preferencesnamespacekryon_sec), which is wiped during a full flash format. On subsequent boot, a new random key was generated, altering the derived master key and causing the backup's HMAC authentication tag to fail validation. - Re-architected
CryptoEngine::getDeviceKeyto derive a permanent 256-bit cryptographic Hardware Root Key ($K_{\text{hw}}$ ) directly from immutable silicon eFuses burned into wafer registers at the Espressif factory:- Combines Factory Base MAC (
esp_efuse_mac_get_default), WiFi STA MAC (esp_read_mac), Bluetooth MAC, 64-bit eFuse MAC (ESP.getEfuseMac()), Chip Model, Chip Revision, and CPU Core count. - Hashes the immutable hardware identity block via HMAC-SHA256 with domain separation key
KRYON_OS_DISASTER_RECOVERY_ROOT_SALT_V1. - Guarantees
$K_{\text{hw}}$ is 100% deterministic and permanent across any number of flash erasures on that physical chip, while remaining completely unique to that silicon die (preventing unauthorized restoration on stolen or different devices).
- Combines Factory Base MAC (
- Added backward-compatible fallback (
CryptoEngine::getLegacyNVSKey):BackupManager::restoreBackupautomatically verifies backups with the permanent hardware silicon key first, and if unverified, falls back to legacy NVS keys for archives created on non-erased devices prior to this fix.
- Fixed issue in the Secure MicroSD Card Backup & Disaster Recovery Subsystem where a device-locked backup created before a full flash wipe (
-
MP3 Playback Stack Canary Overflow Crash (
KryonAudioTask):- Fixed
Guru Meditation Error: Core 0 panic'ed (Unhandled debug exception). Debug exception reason: Stack canary watchpoint triggered (KryonAudioTask)atmp3d_synth_granule/mp3dec_decode_framewhen attempting to play MP3 audio in the music player. - Eliminated massive 20.7 KB stack allocation inside the FreeRTOS audio decoding task:
- Moved
mp3dec_scratch_t scratch(16,160 bytes containing MDCT synthesis and polyphase filterbank buffers) insidesrc/Hal/Audio/minimp3.hfrom a local stack variable into the static BSS segment. - Moved
pcmFrame[MINIMP3_MAX_SAMPLES_PER_FRAME](4,608 bytes) insideAudioEngine::audioTaskinto static BSS (s_pcm_frame). - Doubled
KryonAudioTaskFreeRTOS task stack size from 8,192 bytes (8 KB) to 16,384 bytes (16 KB), providing vast headroom for file I/O, ID3 tag parsing, and I2S DMA streaming without risk of stack canary triggers.
- Moved
- Fixed
-
Web Server Inaccessibility, Network Apps "Error HTTP -1" & WiFi/BLE Coexistence Fix:
- Fixed bug where the Web Server (
WebManager) was unreachable from external devices (browsers on PC/phone) and network applications (App Store, Help Center, OTA Updater) failed withError HTTP -1despite WiFi showing connected. - Reclaimed ~101 KB of contiguous Internal SRAM (
MALLOC_CAP_INTERNAL) required bymbedtls(WiFiClientSecure) andAsyncTCP/lwIP:- Moved
s_png(PNGdecdecoder context, 45,604 bytes) andlineBuffer(960 bytes) insrc/Hal/Graphics/ImageRenderer.cppout of static.dram0.bssinto on-demand PSRAM/heap allocation duringdrawPNG(). - Moved
mp3dec_scratch_t(16,236 bytes) insrc/Hal/Audio/minimp3.hands_mp3dec(6,668 bytes) /s_pcm_frame(4,608 bytes) insrc/Hal/Audio/AudioEngine.cppout of static.dram0.bssinto on-demand PSRAM/heap allocation during MP3 playback. - Reduced
KryonAudioTaskstack from 16 KB to 6 KB andARDUINO_LOOP_STACK_SIZEfrom 32 KB to 16 KB, dropping total static internal RAM utilization from 58.7% (192,260 bytes) down to 36.1% (118,196 bytes). This guaranteesmbedtls_ssl_setup()always has ample contiguous internal DRAM for its 32 KB+ TLS input/output record buffers.
- Moved
- Resolved
WebManagerout-of-memory connection stall on HTTP root requests:filemanager_html(89 KB) andlogin_html(15 KB) were previously passed asconst char*tobeginResponse(), forcing ESPAsyncWebServer to allocate massive contiguous heapStringbuffers that failed on ESP32 RAM. Refactored to stream directly from flash memory chunks ((const uint8_t*)content, len) with zero heap overhead, preventing browserERR_EMPTY_RESPONSEand connection resets. - Fixed
WiFiClientSecuresocket and connect timeout misconfiguration:client.setTimeout(15000)incorrectly interpreted its argument in seconds rather than milliseconds (setting a 4.16-hour socket timeout), whileHTTPClientdefaulted to a restrictive 5-second_connectTimeout(HTTPCLIENT_DEFAULT_TCP_TIMEOUT). Implemented unifiedTLSHelper::configureHTTP(http, 30000)setting 30-second connection and socket timeouts acrossAppStoreUI,OTAManager,HelpCenterUI, andNetworkClient. - Fixed lwIP DNS server memory corruption in
WiFiManager::connectTo: resolved out-of-bounds array write fromdns_setserver(2, &dns2)on ESP-IDF whereDNS_MAX_SERVERSis 2 (valid indices: 0 and 1). Secondary fallback DNS (8.8.8.8) is now safely registered at index 1 without corrupting lwIP heap structures. - Enforced hardware-level modem sleep disabling via direct ESP-IDF driver call (
esp_wifi_set_ps(WIFI_PS_NONE)) inWiFiManager,WebManager::startServer(), andTLSHelper::configureTLS(). This bypasses Arduino's internal_sleepEnabledstate cache and guarantees the 2.4 GHz radio never sleeps, eliminating dropped TCP SYN packets on port 80 and multi-packet TLS certificate exchanges. - Added comprehensive mbedTLS error reporting (
client.lastError(tlsErrBuf)) inAppStoreUI,OTAManager, andHelpCenterUIto output exact mbedtls diagnostic codes instead of generic-1. - Resolved internal SRAM exhaustion between Bluedroid (BLE) and
WiFiClientSecure(mbedtls): whenBluetoothEngineauto-enabled on boot, Bluedroid consumed ~65 KB of internal DRAM (MALLOC_CAP_INTERNAL), starvingmbedtlsof the ~40 KB contiguous internal RAM needed for HTTPS handshakes (Error HTTP -1).BluetoothEngine::init()now stays in standby on boot when WiFi is active, andTLSHelper::configureTLS()/WebManager::startServer()automatically suspend active BLE before allocating TLS buffers or starting the HTTP server. - Fixed
abort()crash incoex_core_enable(esp_bt_controller_enable): ESP-IDF's single-antenna software coexistence requiresWIFI_PS_MIN_MODEM(WiFi.setSleep(true)) whenever both WiFi and Bluetooth are active simultaneously.BluetoothEngine::enable()now enforcesesp_wifi_set_ps(WIFI_PS_MIN_MODEM)prior toBLEDevice::init(), andBluetoothEngine::disable()restoresWIFI_PS_NONE(WiFi.setSleep(false)) when BLE turns off. - Added automatic BLE teardown in
JSBindings::cleanup()when exiting JavaScript apps so background BLE services (blekeyboard,bttest) immediately return internal SRAM and full 2.4 GHz radio bandwidth to the OS. - Resolved 0.0.0.0 DHCP race condition in
WiFiManager::connectTo: previously the connection loop exited immediately upon 802.11 link association (WL_CONNECTED), before DHCP IP lease assignment was complete. Connection loop now waits until bothWiFi.status() == WL_CONNECTEDandWiFi.localIP() != 0.0.0.0. - Updated
WiFiManager::isConnected()to strictly check(WiFi.status() == WL_CONNECTED && WiFi.localIP() != IPAddress(0, 0, 0, 0)), preventing apps from making HTTP requests or binding the Web Server to0.0.0.0. - Added pre-flight DNS hostname resolution (
WiFi.hostByName) with exponential retry inAppStoreUI,HelpCenterUI, andOTAManager, providing clear diagnostic messages ("DNS Lookup Failed!") instead of obscure-1connection errors. - Fixed premature WiFi disconnection in
WiFiManager::smartAutoConnect(): WAN captive portal test failure no longer disconnects an active network unless another matching candidate AP is actually discovered in range. - Added full TLS/HTTPS support (
WiFiClientSecure+TLSHelper::configureTLS) inHelpCenterUI::downloadFile, which previously called rawhttp.begin(url)on HTTPS URLs without TLS configuration. - Added automatic Web Server cleanup and recovery in
WiFiManager::backgroundLoop(): cleanly stops the web server on WiFi link or IP lease loss so that it properly re-binds to the new IPv4 address upon reconnection. - Added CORS pre-flight
OPTIONShandler and/index.htmlalias route inWebManagerto prevent browser connection stalls.
- Fixed bug where the Web Server (
-
LilyGO T-Deck Plus Battery Gauge Fix (Closed-Loop Hardware Hybrid & Fluctuation Elimination):
- Fixed issue where connecting the charger caused battery percentage to immediately jump to 100% instead of showing actual remaining capacity.
- Eliminated the broken taper cutoff in
getEstimatedOCV()that removed loop resistance compensation when terminal voltage reached$\ge 4.20\text{V}$ , exposing the charger's compliance voltage directly to the lookup table. - Implemented closed-loop Ohm's law compensation (
$V_{\text{core}} = V_{\text{terminal}} - \Delta V_{\text{offset}}$ ) based on real live physical ADC measurements on GPIO 4 with loop impedance compensation ($R_{\text{loop}} = 0.38,\Omega$ ,$I_{\text{charge}} = 450,\text{mA}$ ) and Constant Voltage (CV) saturation tapering. - Added a 12-second chemical settling cross-fade anchor on charger connection, preventing instantaneous plug-in voltage surges from spiking the fuel gauge.
- Eliminated battery percentage jitter and top-bar screen flickering using a 5-sample median window filter, heavy exponential moving average (
$\alpha = 0.04$ ,$\tau \approx 5.5\text{s}$ ), monotonic discharge decay clamping, and a$\pm 0.8%$ integer hysteresis display deadband. - Added state preservation in ESP32-S3 RTC Fast Memory (
RTC_DATA_ATTR s_rtc_last_soc), ensuring warm reboots and sleep wakeups resume seamlessly from the last recorded battery state.
-
LilyGO T-Deck Plus False Charger Detection & Rapid Cycling Fix:
- Fixed bug where the device rapidly connected and disconnected from charging state every second (causing repetitive charger chime playback and top bar icon toggling) while operating purely on battery power.
- Eliminated unreliable
HWCDC::isPlugged()dependency: on battery power with no USB cable connected, the floating D+/D- pins on ESP32-S3 picked up ambient electrostatic noise, causingHWCDC::isPlugged()to flap between true and false every second. - Initialized voltage rolling history on boot with actual battery voltage, eliminating transient comparisons against zero.
- Implemented a 2-second debounced confirmation state machine with genuine physical thresholds:
- Entry requires 2 consecutive seconds of genuine charger connection evidence: high CV float (
$\ge 4.28\text{V}$ ), current-reversal step surge ($\ge +120\text{mV}$ from$-180\text{mA}$ discharge to$+450\text{mA}$ charge), or positive charging slope ($\ge +35\text{mV}$ over 5s). - Exit requires 2 consecutive seconds of disconnection evidence: step drop (
$\le -100\text{mV}$ ) or decay below charging floor ($< 4.12\text{V}$ ).
- Entry requires 2 consecutive seconds of genuine charger connection evidence: high CV float (
-
On-Screen Keyboard Double-Press Glitch (MyKeyboard):
- Fixed bug where pressing an on-screen keyboard key once caused the character to type twice.
- Resolved root cause where a static delay(200) timeout was shorter than standard human capacitive touch contact (250-350ms), causing subsequent loop iterations to re-trigger the key before the finger was lifted.
- Added physical touch-release wait loop (while (TouchDriver::getTouch(&rx, &ry)) delay(10);) ensuring every screen tap registers exactly one character.
- Integrated smooth hold-to-repeat support for DEL / Backspace when held for more than 450ms.
-
BLE HID Keyboard LoadProhibited Panic & Reconnect Notification Fix:
- Fixed
Guru Meditation Error: Core 1 panic'ed (LoadProhibited)duringBluetoothEngine::startKeyboard()caused byBLEHIDDevice::manufacturer(std::string)dereferencing an uninitializedm_manufacturerCharacteristicpointer inESP32 BLE Arduino @ 2.0.0. Now calls 0-args_pHidDev->manufacturer()first to allocate the0x2A29characteristic on the Device Info service before invokingsetValue("KryonOS"). - Added standard 5-bit LED output report (
s_pHidDev->outputReport(1)) to the USB HID report map and explicitly enabledBLE2902CCCD notifications ons_pHidInputReportands_pHidMediaReportso bonded smartphones (iOS/Android) receive key notifications across reconnections. - Added
bt_reset_server_state()when toggling radio power and preserved active GATT services acrossstopKeyboard()calls to prevent stalegatts_ifhandle panics.
- Fixed
-
System Display Dimension Function Aliases & JS TypeError:
- Fixed
TypeError: undefined not callable (property 'width' of [object Object])when apps invokedSystem.width()orSystem.height(). - Added native C++ bindings for
System.width(alias ofSystem.screenWidth) andSystem.height(alias ofSystem.screenHeight) insrc/Runtime/JSBindings.cpp. - Updated
test/com.kryonos.blekeyboard/main.jswith defensive property resolution(typeof System.screenWidth === "function") ? System.screenWidth() : ....
- Fixed
-
Wave Player Infinite Timer & Track Completion Bug:
- Fixed bug where playback timer continued counting infinitely past the track's duration instead of stopping or advancing.
- Resolved guard condition in
playTrackthat blocked auto-repetition and track advance whenisPlayingwas still set. - Synchronized track duration and live position with hardware I2S DMA metrics via
Speaker.getDuration()andSpeaker.getPosition(). - Added strict duration clamping ensuring
elapsedSecstops exactly at total duration upon track completion across all repeat modes (ALL,ONE,OFF).
-
Duktape ES5.1 Promise Hoisting & globalThis Reference Bug:
- Fixed
TypeError: undefined not callable (property 'then' of [object Object])in Bluetooth JavaScript APIs. - Resolved ES5.1 function declaration hoisting inside closures that caused
typeof Promise === 'undefined'to evaluate tofalse, leavingPromise.prototype.thenundefined on new Promise instances. - Replaced modern ES2020
globalThisreferences with universal cross-environment global resolution (Function('return this')()). - Added safe error evaluation (
duk_peval_string) injs_init_bluetoothlogging any bootstrap errors to the hardware serial console.
- Fixed
-
Bluetooth Event Queue Pump in JavaScript Execution Loop & Scanner Reliability:
- Fixed issue where
BluetoothEngine::poll()was not called during JavaScript application execution, causing incoming BLE advertisement packets and GATT notifications to remain queued in C++ ring buffers without triggering theBluetooth.BLE.Scanner.on('discover')or characteristicon('valueChange')callbacks. - Added
BluetoothEngine::poll()directly intoJSBindings::js_delay(ctx)so that all events are dequeued and dispatched on everySystem.delay(ms)frame tick. - Exposed
Bluetooth.poll()in the global JavaScript namespace for explicit manual queue polling. - Updated default scanner parameters to continuous mode (
timeout: 0) and near 100% duty cycle (interval: 100ms,window: 99ms), ensuring brief advertising bursts from smartphones and beacons are captured reliably. - Added real-time serial output diagnostics in
BluetoothEngine([BLE Scan] Starting scan,[BLE Scan] Discovered: <name> (<mac>) RSSI: <rssi> dBm,[BLE Scan] Hardware scan cycle completed) for physical hardware verification over USB Serial. - Optimized
test/com.kryonos.bttest/main.jswith batch screen refreshes (scanDirty = true) and fallback labeling (e.g.BLE (AB:CD)) for devices broadcasting without GAP name strings.
- Fixed issue where
-
WebManager AsyncTCP Cross-Task Mutex Assertion Panic:
- Fixed
assert failed: xQueueGenericSend queue.c:832 (pxQueue->u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle())occurring when WebManager handled incoming HTTP requests for SD card storage. - Removed cross-thread
tft.dmaWait()andtft.endWrite()invocations fromprepareSDSPI()insideWebManager.cpp. Backgroundasync_tcpworker tasks now isolate the shared SPI bus solely via GPIO chip-select lines (TFT_CS,RADIO_CS_PIN) without illegally releasing the main thread's FreeRTOS SPI transaction mutex.
- Fixed
-
AudioEngine PSRAM Multi-Heap Corruption & Race Condition:
- Fixed
CORRUPT HEAP: Bad head(multi_heap_poisoning.c:259) when selecting and playing WAV music tracks. - Eliminated cross-core double-free race condition by synchronizing
AudioEngine::stop()with Core 0audioTask:stop()now signalss_stop_requestedand waits foraudioTaskto acknowledge and exit its playback loop before freeing PSRAM memory unders_audio_mutex. - Transferred
s_psram_file_bufferownership exclusively to the main thread unders_audio_mutex, eliminating re-entrant/concurrent heap deallocations from the audio worker task. - Increased
s_dma_chunkallocation toDMA_CHUNK_SAMPLES(4096 samples / 8192 bytes) with strict array bounds checks, preventing 8-bit mono downmix sample expansion from overflowing into adjacent PSRAM heap canaries. - Added edge detection (
lastTouchPressed) and continuous vs. tap touch event partitioning in Wave Player (test/com.kryonos.musicplayer), preventing rapid multi-invocation ofSpeaker.playWavacross consecutive display frames during a single touch tap.
- Fixed
-
Background WiFi Scan Freezing Loop:
- Eliminated the recurring 15-second background auto-scan loop (
WiFi.scanNetworks(false, false)) inWiFiManager::backgroundLoop()when disconnected from Wi-Fi. - Prevents the LilyGO T-Deck Plus and ESP32 core from freezing, stuttering, or dropping UI/touch response while offline; Wi-Fi scanning and reconnection are now strictly user-initiated via Settings or manual prompts.
- Eliminated the recurring 15-second background auto-scan loop (
-
MicroSD WAV Audio Screeching & Metadata Noise:
- Replaced fixed 44-byte WAV header assumption with a chunk-accurate RIFF parser (
parseWavStream) that navigatesfmtanddatasubchunks and gracefully skips extended format blocks (cbSize), padding chunks (JUNK), and broadcast headers (bext). - Added bounded stream enforcement to stop playback precisely when the audio
datachunk finishes, preventing trailingLIST,INFO, andID3tags from being sent to the MAX98357A I2S DAC as harsh digital noise. - Implemented automatic PSRAM file buffering (
s_psram_file_buffer) for MicroSD WAV playback (up to 6 MB), completely isolating playback from the shared SPI bus during audio streaming and preventing hardware SPI collisions with concurrent ST7789 display refresh frames. - Added
i2s_zero_dma_bufferand zero-crossing de-click ramp down on playback stop to eliminate lingering pops or hums.
- Replaced fixed 44-byte WAV header assumption with a chunk-accurate RIFF parser (
-
AudioEngine Master Volume Clobbering & Linear Distortion:
- Fixed issue where
AudioEngine::playToneandAudioEngine::playBeepwere directly overwriting master volume (s_volume). Replaced with a separate relatives_tone_volumeso user master volume is never altered by tone/beep playback. - Implemented human-ear perceptual quadratic volume scaling (
$V_{\text{perceived}} = (\text{vol}/100)^2$ ) for both tone synthesis and WAV DMA chunk processing, ensuring lowering the volume slider produces distinct audible attenuation rather than flatline loudness.
- Fixed issue where
-
Trackball ISR Debouncing & Cross-Talk:
- Resolved hardware GPIO 0 collision between MAX98357A I2S master clock and trackball click by setting
.mck_io_num = I2S_PIN_NO_CHANGE. - Added dominant-axis filtering and 110ms edge cooldown to prevent unstable automatic navigation.
- Resolved hardware GPIO 0 collision between MAX98357A I2S master clock and trackball click by setting
Firmware Binaries & Flash Offsets
| Board Target | File Name | Flash Offset | Role | SHA-256 Checksum |
|---|---|---|---|---|
| esp32-s3-devkitc-1-n16r8 | KryonOS-v3.0.0-esp32-s3-devkitc-1-n16r8-bootloader-0x0000.bin |
0x0000 |
Bootloader | 2a71d69b471e20c2bac7fb469f3c6a807b3ebee780e348e5889db0da849ca363 |
| esp32-s3-devkitc-1-n16r8 | KryonOS-v3.0.0-esp32-s3-devkitc-1-n16r8-partitions-0x8000.bin |
0x8000 |
Partition Table | bd0f7954aca2ef7d925ee21aaa1f3dc8822d1d6ce5cbbd26a135e5886bfff6ce |
| esp32-s3-devkitc-1-n16r8 | KryonOS-v3.0.0-esp32-s3-devkitc-1-n16r8-firmware-0x10000.bin |
0x10000 |
Firmware (App) | 7031566f1fd2c3a2ecf5e5c0fb0243abe3d737c298baddbbeabfc4c5b43cb257 |
| lilygo-t-deck | KryonOS-v3.0.0-lilygo-t-deck-bootloader-0x0000.bin |
0x0000 |
Bootloader | 2a71d69b471e20c2bac7fb469f3c6a807b3ebee780e348e5889db0da849ca363 |
| lilygo-t-deck | KryonOS-v3.0.0-lilygo-t-deck-partitions-0x8000.bin |
0x8000 |
Partition Table | bd0f7954aca2ef7d925ee21aaa1f3dc8822d1d6ce5cbbd26a135e5886bfff6ce |
| lilygo-t-deck | KryonOS-v3.0.0-lilygo-t-deck-firmware-0x10000.bin |
0x10000 |
Firmware (App) | fe80e0a7585aee9ffec930679c97c21ee1da84583978b955a3731830e4fb1b74 |
| lilygo-t-hmi | KryonOS-v3.0.0-lilygo-t-hmi-bootloader-0x0000.bin |
0x0000 |
Bootloader | 1776e4dd896a69d0a5c2e79957b0e2a88aa4129b1381d6478683515a1f6af343 |
| lilygo-t-hmi | KryonOS-v3.0.0-lilygo-t-hmi-partitions-0x8000.bin |
0x8000 |
Partition Table | bd0f7954aca2ef7d925ee21aaa1f3dc8822d1d6ce5cbbd26a135e5886bfff6ce |
| lilygo-t-hmi | KryonOS-v3.0.0-lilygo-t-hmi-firmware-0x10000.bin |
0x10000 |
Firmware (App) | c5a0aee2f77df1179d60ddf468ac36cb30851d59aa232f23d6a7c35aa8ac8821 |
| m5stack-cardputer | KryonOS-v3.0.0-m5stack-cardputer-bootloader-0x0000.bin |
0x0000 |
Bootloader | 1776e4dd896a69d0a5c2e79957b0e2a88aa4129b1381d6478683515a1f6af343 |
| m5stack-cardputer | KryonOS-v3.0.0-m5stack-cardputer-partitions-0x8000.bin |
0x8000 |
Partition Table | f847fbb42780b47e31b109c26586d84f0518292d514901fb58610e397c55db14 |
| m5stack-cardputer | KryonOS-v3.0.0-m5stack-cardputer-firmware-0x10000.bin |
0x10000 |
Firmware (App) | 79ab495da2dc870519778cf49bbcef570a72441a975d56cd6fa35d680444f185 |