/*
Took care of that damn blinking!
Used LC_baseTools for low level goodies and made up a
class that holds the text as a ring of beads.
Oh, and this version is NON BLOCKING.
For document on LC_baseTools :
https://github.com/leftCoast/LC_libraryDocs/blob/main/LC_libraries.pdf
*/
#include <LiquidCrystal_I2C.h>
#include <lists.h>
#include <strTools.h>
#include <timeObj.h>
// **************** class aChar ****************
class aChar : public linkListObj {
public:
aChar(char inChar);
virtual ~aChar();
char getChar(void);
char ourChar;
};
aChar::aChar(char inChar) { ourChar = inChar; }
aChar::~aChar() { }
char aChar::getChar(void) { return ourChar; }
// *************** class charRing ***************
class charRing : public linkList {
public:
charRing(const char* inStr);
virtual ~charRing(void);
char* getSubstr(int offset,int nunChars);
char* ourStr;
char* returnStr;
};
charRing::charRing(const char* inStr) {
aChar* newChar;
int i;
returnStr = NULL;
heapStr(&returnStr,inStr); // Q&D way to get string allocated.
if (returnStr) { // We got it?
i = 0; // Start building the loop.
while(inStr[i]) { // For every non-null char..
newChar = new aChar(inStr[i]); // Create a node for it and stuff it in.
addToEnd(newChar); // Add the new node to our list.
i++; // Don't forget to bump i.
} //
newChar->setNext(theList); // Make it a loop.
} //
}
// Little tricky here. We made it into a ring so no NULL
// at the end to know where to stop.
charRing::~charRing(void) {
aChar* trace;
freeStr(&returnStr); // Knock this out first.
trace = (aChar*)theList; // Grab at the ring..
if (trace) { // Got a ring?
while(trace && trace->getNext()!=(aChar*)theList) { // While we have a ring and this guys't not pointint at it too..
trace = (aChar*)trace->getNext(); // Move up the ring one..
} //
if (trace) { // If we popped out with trace!=NULL? We found the end.
trace->setNext(NULL); // Now the auto destructor shoudld work.
}
}
}
char* charRing::getSubstr(int offset,int numChars) {
aChar* trace;
if (returnStr && numChars) { // Input make sense?
trace = (aChar*)theList; // Make a grab at the bead we're holding.
while(trace && offset>0) { // While we have a bead and + offset..
trace = (aChar*)(trace->getNext()); // Move to th enext bead.
offset--; // bump down the offset.
} //
theList = trace; // Move what we are holding to this bead.
for(int i=0;i<numChars;i++) { // Setup for substring copy.
returnStr[i] = trace->getChar(); // Start fiulling returnStr.
returnStr[i+1] = '\0'; // Pop a endstring after each write. (Lazy)
trace = (aChar*)(trace->getNext()); // Move to next bead.
} // By now the substring is ready.
} //
return returnStr; // Hand it over to the user.
}
// *************** Your sketch ***************
char firstLine[16] = "Static 1st line";
char secondLine[] = " Scrolling text on second line";
charRing ourScroller(secondLine); // The set of string beads.
timeObj scrollTimer(250); // Wait time per letter.
LiquidCrystal_I2C lcd(0x27, 16, 2); // The LCD.
void setup() {
lcd.init(); // Fire up the LCD.
lcd.backlight(); // And the backlight.
lcd.print(firstLine); // First line is static. So print it once.
}
void loop() {
char* subsetStr;
if (scrollTimer.ding()) { // If the timer went off..
lcd.setCursor(0, 1); // Position ourselselves at the second line.
subsetStr = ourScroller.getSubstr(1,16); // Offset the chars by one and give me 16 of 'em.
lcd.print(subsetStr); // Print that subset.
scrollTimer.start(); // Restart the timer.
}
}