From 3eae5061a4511e347ee94cae3ff364f08f258813 Mon Sep 17 00:00:00 2001 From: Sebastian Nieto Date: Mon, 21 Sep 2026 23:54:50 -0300 Subject: [PATCH] fix(ui): resolver reinicio por falta de RAM limitando sprite a 25KB y ralentizar transicion a 16 cuadros suaves --- sketch/obd2_gauge/meter.h | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/sketch/obd2_gauge/meter.h b/sketch/obd2_gauge/meter.h index 58fde35..8d1afae 100644 --- a/sketch/obd2_gauge/meter.h +++ b/sketch/obd2_gauge/meter.h @@ -1276,12 +1276,10 @@ inline void renderPage0ToSprite(TFT_eSprite &s, int x_offset, int y_slice, int s } String numStr = (val <= -900.0f) ? "---" : String(val, digit); - s.loadFont(DSEG7_Modern_BoldItalic_34); s.setTextColor(priCol, bgCol); s.setTextPadding(114); s.drawRightString(numStr.c_str(), qx + 152, qy + 70, 1); s.setTextPadding(0); - s.unloadFont(); } // Crosshair dividers @@ -1356,12 +1354,10 @@ inline void renderPage1ToSprite(TFT_eSprite &s, int x_offset, int y_slice, int s // Value text String numStr = (val <= -900.0f) ? "---" : (isInt ? String((int)val) : String(val, 1)); - s.loadFont(DSEG7_Modern_BoldItalic_34); s.setTextColor(accentCol, cardBg); s.setTextPadding(100); s.drawRightString(numStr.c_str(), cardX + 262, cardY + 22, 1); s.setTextPadding(0); - s.unloadFont(); s.setTextColor(0xC618, cardBg); s.drawString("`C", cardX + 268, cardY + 32, 2); @@ -1369,23 +1365,23 @@ inline void renderPage1ToSprite(TFT_eSprite &s, int x_offset, int y_slice, int s } // 100% Flicker-Free Double-Buffered Mobile Slide Transition +// Safe 25KB sprite with single font load and smooth ease-out pacing inline void animateSlideTransition(bool swipeLeft) { - touchBeep(); + const int slice_h = 40; // 320x40 = only 25KB (100% safe, leaves 70KB+ free for Bluetooth) + const uint8_t numSlices = 240 / slice_h; // exactly 6 slices TFT_eSprite spr(&tft); - int slice_h = 240; - // Try 320x240 full double-buffer first; if heap is tight, allocate two 320x120 slices - if (spr.createSprite(320, 240) == nullptr) { - slice_h = 120; - if (spr.createSprite(320, 120) == nullptr) { - return; // Fallback: switch instantly without crashing if RAM is fully depleted - } + if (spr.createSprite(320, slice_h) == nullptr) { + return; // Safety fallback } - const uint8_t FRAMES = 10; - // Smooth cubic ease-out deceleration curve - const int16_t step_shifts[FRAMES] = { 45, 92, 140, 186, 228, 264, 290, 308, 317, 320 }; - uint8_t numSlices = (slice_h == 240) ? 1 : 2; + spr.loadFont(DSEG7_Modern_BoldItalic_34); // Loaded ONCE before animation loop! + + const uint8_t FRAMES = 16; + // Cubic ease-out deceleration curve over 16 frames: smooth, visible and elegant + const int16_t step_shifts[FRAMES] = { + 28, 62, 102, 144, 184, 218, 246, 268, 284, 296, 305, 311, 315, 318, 319, 320 + }; for (uint8_t f = 0; f < FRAMES; f++) { int16_t shift = step_shifts[f]; @@ -1420,14 +1416,16 @@ inline void animateSlideTransition(bool swipeLeft) { spr.fillCircle(167, 2, 2, (splitX <= 160) ? getThemePrimaryColor() : 0x5AEB); } - // Direct single SPI push: ZERO visual flicker! + // Direct single SPI push per slice: ZERO visual flicker! spr.pushSprite(0, y_slice); } - delay(8); + yield(); // Feed watchdog and give Bluetooth scheduler CPU cycles + delay(14); // Pacing for smooth, readable transition (~360ms total) } - spr.deleteSprite(); + spr.unloadFont(); // Unload font once at the end + spr.deleteSprite(); // Release the 25KB } /*-------------------*/