FTP task on core 0 at priority 2 starved the WiFi networking stack,
preventing the FTP welcome banner from being sent. Moved to core 1
with 2ms yield to coexist with LVGL rendering.
Move ftpSrv.handleFTP() from Arduino loop() into a dedicated FreeRTOS
task pinned to core 0, leaving core 1 free for LVGL display updates.
FTP callbacks now only set volatile flags (ftp_ui_dirty, ftp_sd_dirty)
which the main loop polls to safely update UI and NeoPixel from core 1.
This eliminates the 20-second PASV data connection timeouts caused by
handleFTP() competing with display.update() for CPU time.
Also fix pre-existing BLACK constant build error in display_manager.cpp.
- Add ftpSrv.setLocalIp() for correct PASV response IP (fixes transfers)
- Move battery indicator to WiFi SSID line, right-aligned
- Fix battery label tilt: fixed width + LV_TEXT_ALIGN_RIGHT
- Fix calcDirSize: use f.path() for full path in recursive walk
- Define FTP_SERVER_NETWORK_TYPE=6 and STORAGE_TYPE=10 directly to bypass
FtpServerKey.h platform detection that was overriding storage to FFAT
- Fix calcDirSize: properly close files, use name() for recursive path
- Add SD debug logging for used-space calculation
- This fixes file transfers (read/write) failing via FTP
- Add BQ27220 fuel gauge: reads SOC percentage every 5s
- Add BQ25896 PMIC: detects charging status (pre-charge/fast/done)
- Add MAX31329 external RTC: reads time on boot, syncs from NTP
- Battery UI: icon + percentage in header, cyan when charging
- Fix SD used bytes: fallback to recursive dir walk when usedBytes() returns 0
- Libraries: PMIC_BQ25896, kode_bq27220, kode_MAX31329
- Fix FTP using FFAT instead of SD_MMC: define both NETWORK_TYPE (6) and
STORAGE_TYPE (10) with numeric values to bypass FtpServerKey.h guard
- Fix SD capacity showing 'f/f GB': use integer math instead of floats
(LVGL builtin sprintf lacks %f support)
- Fix time/date labels tilting 45°: set fixed width + LV_TEXT_ALIGN_CENTER
- Switch LVGL sprintf to C stdlib for future float compatibility