mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-09-11 09:04:53 +00:00
[P157] Add Circular scroll option
This commit is contained in:
@@ -30,6 +30,7 @@
|
||||
//
|
||||
|
||||
/** History
|
||||
* 2026-06-14 tonhuisman: Add Circular scroll option, guarded with define P157_SCROLL_CIRCULAR, settings collapsed by default
|
||||
* 2026-06-13 tonhuisman: Add Scroll Always option to also scroll content <= display width
|
||||
* Add Zero with slash option
|
||||
* Add Delay to next scroll-start option
|
||||
@@ -76,6 +77,9 @@ boolean Plugin_157(uint8_t function, struct EventStruct *event, String& string)
|
||||
uint32_t lSettings{};
|
||||
bitWrite(lSettings, P157_OPTION_ZEROSLASH, true); // Enable zero with slash by default
|
||||
P157_CFG_FLAGS = lSettings;
|
||||
# if P157_SCROLL_TEXT && P157_SCROLL_CIRCULAR
|
||||
P157_SET_SEPARATOR_COUNT(1);
|
||||
# endif
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -168,6 +172,36 @@ boolean Plugin_157(uint8_t function, struct EventStruct *event, String& string)
|
||||
addUnit(F("1..600 = 0.1..60 sec/step"));
|
||||
addFormNumericBox(F("Delay to next scroll-start"), F("scrolldelay"), P157_CFG_SCROLLDELAY, 0, 6000);
|
||||
addUnit(F("0.1 sec"));
|
||||
|
||||
# if P157_SCROLL_CIRCULAR
|
||||
{
|
||||
addFormDetailsStart(F("Circular scroll options"), P157_GET_CIRCULAR_SCROLL);
|
||||
addFormCheckBox(F("Circular scroll"), F("sc_cir"), P157_GET_CIRCULAR_SCROLL);
|
||||
const __FlashStringHelper *sepChars[] = {
|
||||
F("(Space)"),
|
||||
F("-"),
|
||||
F("/"),
|
||||
F("|"),
|
||||
F("\\"),
|
||||
};
|
||||
const int sepCharOptions[] = {
|
||||
' ',
|
||||
'-',
|
||||
'/',
|
||||
'|',
|
||||
'\\',
|
||||
};
|
||||
|
||||
if (0 == P157_GET_CIRCULAR_SEPARATOR) { P157_SET_CIRCULAR_SEPARATOR(sepCharOptions[0]); }
|
||||
|
||||
constexpr size_t optionCount = NR_ELEMENTS(sepCharOptions);
|
||||
const FormSelectorOptions selector(optionCount, sepChars, sepCharOptions);
|
||||
selector.addFormSelector(F("Separator character"), F("sep_char"), P157_GET_CIRCULAR_SEPARATOR);
|
||||
addFormNumericBox(F("Nr. of separator characters"), F("sep_cnt"), P157_GET_SEPARATOR_COUNT, 0, 15);
|
||||
addFormCheckBox(F("Wrap separator with spaces"), F("sc_wrap"), P157_GET_SEPARATOR_WRAP);
|
||||
addFormDetailsEnd();
|
||||
}
|
||||
# endif // if P157_SCROLL_CIRCULAR
|
||||
# endif // if P157_SCROLL_TEXT
|
||||
|
||||
// addFormCheckBox(F("Right-align Temperature (7dt)"), F("temp_rightalign"), bitRead(P157_CFG_FLAGS, P157_OPTION_RIGHTALIGN));
|
||||
@@ -211,6 +245,13 @@ boolean Plugin_157(uint8_t function, struct EventStruct *event, String& string)
|
||||
# endif // if P157_SUPPRESS_ZERO
|
||||
P157_CFG_FLAGS = lSettings;
|
||||
|
||||
# if P157_SCROLL_CIRCULAR
|
||||
P157_SET_CIRCULAR_SCROLL(isFormItemChecked(F("sc_cir")));
|
||||
P157_SET_CIRCULAR_SEPARATOR(getFormItemInt(F("sep_char")));
|
||||
P157_SET_SEPARATOR_COUNT(getFormItemInt(F("sep_cnt")));
|
||||
P157_SET_SEPARATOR_WRAP(isFormItemChecked(F("sc_wrap")));
|
||||
# endif // if P157_SCROLL_CIRCULAR
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -74,6 +74,15 @@ bool P157_data_struct::init(struct EventStruct *event)
|
||||
scrollAll = bitRead(P157_CFG_FLAGS, P157_OPTION_SCROLL_ALL);
|
||||
scrollDelay = P157_CFG_SCROLLDELAY;
|
||||
setScrollSpeed(P157_CFG_SCROLLSPEED);
|
||||
|
||||
# if P157_SCROLL_CIRCULAR
|
||||
scrollCircular = P157_GET_CIRCULAR_SCROLL;
|
||||
circularSeparator = (char)P157_GET_CIRCULAR_SEPARATOR;
|
||||
circularCharCount = P157_GET_SEPARATOR_COUNT;
|
||||
circularWrapSpace = P157_GET_SEPARATOR_WRAP;
|
||||
|
||||
if (scrollCircular) { scrollDelay = 0; } // No delay when using Serpentine scroll
|
||||
# endif // if P157_SCROLL_CIRCULAR
|
||||
# endif // if P157_SCROLL_TEXT
|
||||
suppressLeading0 = bitRead(P157_CFG_FLAGS, P157_OPTION_SUPPRESS0);
|
||||
timesep = true;
|
||||
@@ -384,7 +393,8 @@ int P157_data_struct::getEffectiveTextLength(const String& text) {
|
||||
# if P157_SCROLL_TEXT
|
||||
|
||||
bool P157_data_struct::nextScroll() {
|
||||
bool result = false;
|
||||
bool result = false;
|
||||
uint16_t maxPart = bufLen;
|
||||
|
||||
if (scrollWait && (--scrollWait > 0)) {
|
||||
return result;
|
||||
@@ -406,7 +416,13 @@ bool P157_data_struct::nextScroll() {
|
||||
if (binData.size() > 0) {
|
||||
scrollPos++;
|
||||
|
||||
if (scrollPos > (binData.size() - bufLen)) {
|
||||
if (scrollPos > binData.size() -
|
||||
(
|
||||
# if P157_SCROLL_CIRCULAR
|
||||
scrollCircular ? 1 :
|
||||
# endif
|
||||
bufLen)
|
||||
) {
|
||||
scrollPos = 0; // Redisplay
|
||||
scrollWait = scrollDelay; // Restart delay counter
|
||||
}
|
||||
@@ -422,17 +438,41 @@ bool P157_data_struct::nextScroll() {
|
||||
|
||||
String part = _textToScroll.substring(scrollPos, scrollPos + 1.5 * bufLen);
|
||||
|
||||
while (getEffectiveTextLength(part) > bufLen && !part.isEmpty()) {
|
||||
# if P157_SCROLL_CIRCULAR
|
||||
|
||||
if (scrollCircular) {
|
||||
maxPart = _textToScroll.length();
|
||||
}
|
||||
# endif // if P157_SCROLL_CIRCULAR
|
||||
|
||||
while (getEffectiveTextLength(part) > maxPart && !part.isEmpty()) {
|
||||
part = part.substring(0, part.length() - 1);
|
||||
}
|
||||
|
||||
# if P157_SCROLL_CIRCULAR
|
||||
|
||||
if (scrollCircular) {
|
||||
while (part.length() < bufLen) {
|
||||
for (uint16_t i = 0; i < _textToScroll.length() && part.length() < bufLen; ++i) {
|
||||
part += _textToScroll.charAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif // if P157_SCROLL_CIRCULAR
|
||||
|
||||
for (uint16_t i = 0; i < bufLen && i < part.length(); ++i) {
|
||||
showbuffer[i] = part.charAt(i);
|
||||
}
|
||||
|
||||
scrollPos++;
|
||||
|
||||
if (scrollPos > _textToScroll.length() - bufLen) {
|
||||
if (scrollPos > _textToScroll.length() -
|
||||
(
|
||||
# if P157_SCROLL_CIRCULAR
|
||||
scrollCircular ? 1 :
|
||||
# endif
|
||||
bufLen)
|
||||
) {
|
||||
scrollPos = 0; // Restart when all text displayed
|
||||
scrollWait = scrollDelay; // Restart delay counter
|
||||
}
|
||||
@@ -450,15 +490,32 @@ void P157_data_struct::setTextToScroll(const String& text) {
|
||||
free_string(_textToScroll);
|
||||
|
||||
if (!text.isEmpty()) {
|
||||
_textToScroll.reserve(text.length() + bufLen + (scrollFull ? bufLen : 0));
|
||||
# if P157_SCROLL_CIRCULAR
|
||||
|
||||
for (int i = 0; scrollFull && i < bufLen; ++i) { // Scroll text in from the right, so start with all spaces
|
||||
_textToScroll += ' ';
|
||||
}
|
||||
_textToScroll += text;
|
||||
if (scrollCircular) {
|
||||
_textToScroll.reserve(text.length() + circularCharCount + (circularWrapSpace ? 2 : 0));
|
||||
_textToScroll = text;
|
||||
|
||||
for (int i = 0; i < bufLen; ++i) { // Scroll text off completely before restarting
|
||||
_textToScroll += ' ';
|
||||
if (circularWrapSpace) { _textToScroll += ' '; }
|
||||
|
||||
for (uint8_t i = 0; i < circularCharCount; ++i) {
|
||||
_textToScroll += circularSeparator;
|
||||
}
|
||||
|
||||
if (circularWrapSpace) { _textToScroll += ' '; }
|
||||
} else
|
||||
# endif // if P157_SCROLL_CIRCULAR
|
||||
{
|
||||
_textToScroll.reserve(text.length() + bufLen + (scrollFull ? bufLen : 0));
|
||||
|
||||
for (int i = 0; scrollFull && i < bufLen; ++i) { // Scroll text in from the right, so start with all spaces
|
||||
_textToScroll += ' ';
|
||||
}
|
||||
_textToScroll += text;
|
||||
|
||||
for (int i = 0; i < bufLen; ++i) { // Scroll text off completely before restarting
|
||||
_textToScroll += ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
scrollCount = _scrollSpeed;
|
||||
@@ -491,6 +548,8 @@ void P157_data_struct::logBufferContent(String prefix) {
|
||||
log += ',';
|
||||
log += showperiods[i] ? F(".") : F("");
|
||||
}
|
||||
log += 's';
|
||||
log += scrollPos;
|
||||
addLogMove(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
}
|
||||
@@ -514,12 +573,28 @@ void P157_data_struct::printBuffer() {
|
||||
String log;
|
||||
# endif // ifdef P157_DEBUG
|
||||
|
||||
for (uint16_t j = 0; j < bufLen && (scrollPos + j) < binData.size(); ++j) {
|
||||
ht16k33->writeLowLevel(j, binData[scrollPos + j]);
|
||||
# ifdef P157_DEBUG
|
||||
log += formatToHex(binData[scrollPos + j]);
|
||||
log += ',';
|
||||
# endif // ifdef P157_DEBUG
|
||||
uint16_t j = 0;
|
||||
# if P157_SCROLL_CIRCULAR
|
||||
uint16_t k = 0;
|
||||
# endif
|
||||
|
||||
for (; j < bufLen; ++j) {
|
||||
if ((scrollPos + j) < binData.size()) {
|
||||
ht16k33->writeLowLevel(j, binData[scrollPos + j]);
|
||||
# ifdef P157_DEBUG
|
||||
log += formatToHex(binData[scrollPos + j]);
|
||||
log += ',';
|
||||
# endif // ifdef P157_DEBUG
|
||||
}
|
||||
# if P157_SCROLL_CIRCULAR
|
||||
|
||||
else if (scrollCircular) {
|
||||
ht16k33->writeLowLevel(j, binData[k]);
|
||||
++k;
|
||||
|
||||
if (k >= binData.size()) { k = 0; }
|
||||
}
|
||||
# endif // if P157_SCROLL_CIRCULAR
|
||||
}
|
||||
# ifdef P157_DEBUG
|
||||
|
||||
@@ -1056,7 +1131,11 @@ bool P157_data_struct::plugin_write_7dtext(const String& text) {
|
||||
_lastArgument = text;
|
||||
setTextToScroll(EMPTY_STRING);
|
||||
|
||||
setScrollEnabled(scrollAll || getEffectiveTextLength(text) > bufLen);
|
||||
setScrollEnabled(
|
||||
# if P157_SCROLL_CIRCULAR
|
||||
scrollCircular ||
|
||||
# endif
|
||||
scrollAll || getEffectiveTextLength(text) > bufLen);
|
||||
|
||||
if (isScrollEnabled()) {
|
||||
setTextToScroll(text);
|
||||
@@ -1114,8 +1193,8 @@ bool P157_data_struct::plugin_write_7dbin(const String& text,
|
||||
scrollPos = 0;
|
||||
|
||||
uint32_t wordValue{};
|
||||
uint8_t arg = 1;
|
||||
String argValue = parseStringKeepCaseNoTrim(text, offset + arg);
|
||||
uint8_t arg = offset + 1;
|
||||
String argValue = parseStringKeepCaseNoTrim(text, arg);
|
||||
|
||||
while (!argValue.isEmpty()) {
|
||||
NumericalType numType;
|
||||
@@ -1167,22 +1246,53 @@ bool P157_data_struct::plugin_write_7dbin(const String& text,
|
||||
}
|
||||
}
|
||||
arg++;
|
||||
argValue = parseStringKeepCaseNoTrim(text, offset + arg);
|
||||
argValue = parseStringKeepCaseNoTrim(text, arg);
|
||||
}
|
||||
|
||||
if (binData.size() > 0) {
|
||||
# if P157_SCROLL_TEXT
|
||||
setScrollEnabled(scrollAll || binData.size() > bufLen);
|
||||
setScrollEnabled(
|
||||
# if P157_SCROLL_CIRCULAR
|
||||
scrollCircular ||
|
||||
# endif
|
||||
scrollAll || binData.size() > bufLen);
|
||||
|
||||
if (isScrollEnabled()) {
|
||||
uint8_t i = 0;
|
||||
# if P157_SCROLL_CIRCULAR
|
||||
|
||||
for (; scrollFull && i < bufLen; ++i) { // prepend to start display empty
|
||||
binData.insert(binData.begin(), 0);
|
||||
}
|
||||
if (scrollCircular) {
|
||||
uint16_t bitmap;
|
||||
|
||||
for (i = 0; i < bufLen; ++i) { // append empty to scroll until empty
|
||||
binData.push_back(0);
|
||||
if (circularWrapSpace) { binData.push_back(0); }
|
||||
# if P157_EXTRA_FONTS
|
||||
|
||||
if (P157_is7SegmentDisplay(displayModel)) {
|
||||
// Re-use the fonts from P073, but they use the MAX7219 layout, that has bits 0..6 reverted
|
||||
bitmap = P073_revert7bits(P073_getFontChar(P073_mapCharToFontPosition(circularSeparator, fontSet), fontSet));
|
||||
|
||||
} else
|
||||
# endif // if P157_EXTRA_FONTS
|
||||
{
|
||||
bitmap = ht16k33->getCharacterBitmap(circularSeparator);
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < circularCharCount; ++i) {
|
||||
binData.push_back(bitmap);
|
||||
}
|
||||
|
||||
if (circularWrapSpace) { binData.push_back(0); }
|
||||
} else
|
||||
# endif // if P157_SCROLL_CIRCULAR
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
for (; scrollFull && i < bufLen; ++i) { // prepend to start display empty
|
||||
binData.insert(binData.begin(), 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < bufLen; ++i) { // append empty to scroll until empty
|
||||
binData.push_back(0);
|
||||
}
|
||||
}
|
||||
} else
|
||||
# endif // if P157_SCROLL_TEXT
|
||||
|
||||
@@ -39,9 +39,22 @@
|
||||
# define P157_OPTION_SCROLLFULL 4 // Scroll text from the right in, starting with a blank display
|
||||
# define P157_OPTION_SUPPRESS0 5 // Suppress leading zero on day/hour of Date/Time display
|
||||
# define P157_OPTION_BLINK_DOT 6 // Use dot on second digit for flashing instead of colon
|
||||
# define P157_OPTION_CIRCULAR 7 // Enable circular scrolling (continuous)
|
||||
# define P157_OPTION_CIR_SEPAR 8 // 8 bit Separator character
|
||||
# define P157_OPTION_CIR_COUNT 16 // 4 bit Separator character count
|
||||
# define P157_OPTION_CIR_WRAP 20 // Separator wrap with spaces
|
||||
|
||||
# define P157_GET_CIRCULAR_SCROLL bitRead(P157_CFG_FLAGS, P157_OPTION_CIRCULAR)
|
||||
# define P157_SET_CIRCULAR_SCROLL(V) bitWrite(P157_CFG_FLAGS, P157_OPTION_CIRCULAR, V)
|
||||
# define P157_GET_CIRCULAR_SEPARATOR get8BitFromUL(P157_CFG_FLAGS, P157_OPTION_CIR_SEPAR)
|
||||
# define P157_SET_CIRCULAR_SEPARATOR(V) set8BitToUL(P157_CFG_FLAGS, P157_OPTION_CIR_SEPAR, V)
|
||||
# define P157_GET_SEPARATOR_COUNT get4BitFromUL(P157_CFG_FLAGS, P157_OPTION_CIR_COUNT)
|
||||
# define P157_SET_SEPARATOR_COUNT(V) set4BitToUL(P157_CFG_FLAGS, P157_OPTION_CIR_COUNT, V)
|
||||
# define P157_GET_SEPARATOR_WRAP bitRead(P157_CFG_FLAGS, P157_OPTION_CIR_WRAP)
|
||||
# define P157_SET_SEPARATOR_WRAP(V) bitWrite(P157_CFG_FLAGS, P157_OPTION_CIR_WRAP, V)
|
||||
|
||||
# ifdef USES_P073
|
||||
# define P157_FEATURE_P073 1 // Use P073 shared functions and fonts when available
|
||||
# define P157_FEATURE_P073 1 // Use P073 shared functions and fonts when available
|
||||
# else // ifdef USES_P073
|
||||
# define P157_FEATURE_P073 0
|
||||
# endif // ifdef USES_P073
|
||||
@@ -67,6 +80,9 @@
|
||||
# ifndef P157_SCROLL_TEXT
|
||||
# define P157_SCROLL_TEXT 1 // Enable scrolling of 7dtext by default
|
||||
# endif // ifndef P157_SCROLL_TEXT
|
||||
# ifndef P157_SCROLL_CIRCULAR
|
||||
# define P157_SCROLL_CIRCULAR 1 // Enable continuous scrolling by default
|
||||
# endif // ifndef P157_SCROLL_CIRCULAR
|
||||
# ifndef P157_7DBIN_COMMAND
|
||||
# define P157_7DBIN_COMMAND 1 // Enable input of binary data via 7dbin,uint8_t,... command
|
||||
# endif // ifndef P157_7DBIN_COMMAND
|
||||
@@ -87,6 +103,10 @@
|
||||
# undef P157_SCROLL_TEXT // Optionally activate if .bin file space is problematic, remove the scrolling text feature
|
||||
# define P157_SCROLL_TEXT 0
|
||||
# endif // if P157_SCROLL_TEXT
|
||||
# if P157_SCROLL_CIRCULAR
|
||||
# undef P157_SCROLL_CIRCULAR // Optionally activate if .bin file space is problematic, remove the circular scrolling feature
|
||||
# define P157_SCROLL_CIRCULAR 0
|
||||
# endif // if P157_SCROLL_CIRCULAR
|
||||
# if P157_7DBIN_COMMAND
|
||||
# undef P157_7DBIN_COMMAND // Optionally activate if .bin file space is problematic, remove the 7dbin command
|
||||
# define P157_7DBIN_COMMAND 0
|
||||
@@ -120,6 +140,8 @@ public:
|
||||
bool plugin_ten_per_second(struct EventStruct *event);
|
||||
# endif // if P157_SCROLL_TEXT
|
||||
|
||||
private:
|
||||
|
||||
void printBuffer();
|
||||
void fillBufferWithTime(bool sevendgt_now,
|
||||
uint8_t sevendgt_hours,
|
||||
@@ -202,7 +224,12 @@ public:
|
||||
bool scrollAll = false;
|
||||
bool zeroSlash = false;
|
||||
|
||||
private:
|
||||
# if P157_SCROLL_CIRCULAR
|
||||
bool scrollCircular = false;
|
||||
bool circularWrapSpace = false;
|
||||
char circularSeparator{};
|
||||
uint8_t circularCharCount{};
|
||||
# endif // if P157_SCROLL_CIRCULAR
|
||||
|
||||
uint16_t _scrollSpeed = 0;
|
||||
# endif // P157_SCROLL_TEXT
|
||||
@@ -211,8 +238,6 @@ private:
|
||||
# endif // if defined(P157_SCROLL_TEXT) || defined(P157_7DBIN_COMMAND)
|
||||
String _lastArgument; // Keep last argument for 7dtext and 7dbin
|
||||
|
||||
private:
|
||||
|
||||
Noiasca_ht16k33*ht16k33 = nullptr;
|
||||
uint8_t bufLen{};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user