Scroll speeds below 1 dot per second

scroll_speed is now a float (0.05-30 dots per second, e.g. 0.25 = one dot
every 4 s). Page format 5; version 4 pages are converted, version 3 goes
through version 4.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mangavalkandClaude Opus 5.5 committed 2026-10-16 16:23:16 +02:00
1 parent 1282d16c0b
commit e0a89cec99
17 files changed
+148 -21

No files matched your search

+2 -2
View File
@@ -173,8 +173,8 @@ const char *validatePage(const DynamicPage &page)
if (!isfinite(e.factor) || e.factor == 0)
return "The multiplier must be a number other than 0";
if (e.scroll_width > 2 * BITMAP_WIDTH ||
(e.scroll_width && (e.scroll_speed < SCROLL_SPEED_MIN || e.scroll_speed > SCROLL_SPEED_MAX)))
return "Scrolling: window up to 168 dots, speed 1-30 dots per second";
(e.scroll_width && !(e.scroll_speed >= SCROLL_SPEED_MIN && e.scroll_speed <= SCROLL_SPEED_MAX)))
return "Scrolling: window up to 168 dots, speed 0.05-30 dots per second";
if (e.type == ElementType::HaValue && !validEntityId(e.entity))
return "Home Assistant values need an entity id like sensor.outside_temperature";
if (e.type == ElementType::Bar)
+3 -3
View File
@@ -127,8 +127,8 @@ const int8_t DECIMALS_AS_IS = -1;
const int8_t DECIMALS_MAX = 4;
// Scrolling: dots per second, and the empty dots between the end and the next start
const uint8_t SCROLL_SPEED_MIN = 1;
const uint8_t SCROLL_SPEED_MAX = 30;
const float SCROLL_SPEED_MIN = 0.05f; // one dot every 20 s
const float SCROLL_SPEED_MAX = 30;
const int SCROLL_GAP = 12;
// Background from `start` (minutes since midnight) until the next slot
@@ -158,7 +158,7 @@ struct PageElement
char attribute[ELEMENT_ATTRIBUTE_SIZE] = ""; // empty = the state
float factor = 1; // HaValue: numbers are multiplied by it (e.g. 1000: m3 -> l)
uint8_t scroll_width = 0; // texts: 0, or the width of a window the text scrolls in
uint8_t scroll_speed = 8; // dots per second
float scroll_speed = 8; // dots per second, may be below 1 (0.25: a dot every 4 s)
uint32_t target = 0; // Countdown: minutes since 2000-01-01 00:00 (local time)
// Added in page format 3 (keep new fields at the end, see display/page_store.cpp)
HaShow show = HaShow::Number; // HaValue: how the value is shown
+6 -3
View File
@@ -1,5 +1,6 @@
#include "logic/page_render.h"
#include <math.h>
#include <stdio.h>
#include <string.h>
@@ -157,13 +158,15 @@ static uint32_t drawTextElement(const PageElement &e, const char *text, uint32_t
// Scrolls from right to left, the next round follows after SCROLL_GAP dots
uint32_t period = width + SCROLL_GAP;
uint64_t steps = (uint64_t)now_ms * e.scroll_speed / 1000;
// Step n starts at n * 1000 / speed ms (the speed can be below 1 dot per second)
double ms_per_step = 1000.0 / e.scroll_speed;
uint64_t steps = (uint64_t)(now_ms / ms_per_step);
int offset = (int)(steps % period);
drawText(bitmap, font, left - offset, e.y, text, mode, left, left + area);
drawText(bitmap, font, left - offset + (int)period, e.y, text, mode, left, left + area);
// Until the next step
uint64_t next_step_ms = ((steps + 1) * 1000 + e.scroll_speed - 1) / e.scroll_speed;
uint32_t wait = (uint32_t)(next_step_ms - now_ms);
uint64_t next_step_ms = (uint64_t)ceil((steps + 1) * ms_per_step);
uint32_t wait = next_step_ms > now_ms ? (uint32_t)(next_step_ms - now_ms) : 0;
return wait ? wait : 1;
}