#include <LiquidCrystal.h>
#include "MTScrollText.h"

LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
// "Hello pico!" è in RAM.
char *myString = "Hello pico!";
uint32_t millisOldTime = 0;
uint8_t speedScroll = 30;  // un carattere ogni 30ms

// myScrollD( 20 ) occupa 16 colonne sul display
MTScrollText myScroll( 16 );
/*
    "MauroTec Software Lun 31 Gen 2022"
    " 00:00:00 WokWi Simulator ";

#define LEN_TEXT    59
char textBuff[LEN_TEXT + 1] = {0};
Invece di contare manualmente il numero di caratteri 
di cui è composta la stringa da visualizzare (textBuff)
uso strlen che viene risolto al momento della compilazione
e ricavo in lenText la lughezza per creare textBuff.
Nota che la string literal "MauroTec ... non si trova in 
RAM e quindi non ci sono controidicazioni.
*/
#define LEN_TEXT    lenText
const int lenText = strlen("[MauroTec Software], millis() vale "
    "4294967295 ");

char textBuff[lenText + 1] = {0};
/* Il compilatore ha messo textBuff in RAM all'indirizzo
  0x172 dove si vede che ci sono 46 spazi, quindi lenText
  vale 46.
*/

void showRam() {
  // spazzoliamo tutta la ram cella per cella.
  // come da datasheet inizio da 0x100
  const char *ptrToRam = (char*)0x100;
  // mi servono 16 caselle da 0÷15
  uint8_t counter15 = 15;
  Serial.print(F("addr\t0123456789ABCDEF"));
  // Nota per il 328 RAMEND vale 2303
  for (uint16_t t=0; t<=(RAMEND-0x100); t++) {
   
    if (counter15 == 15) {
      Serial.print("\n");
      Serial.print((uint16_t)ptrToRam, HEX);
      Serial.print("\t");
    } 
    if ((counter15 > -1) && (counter15 < 16)) {
      // vogliamo vedere i caratteri quindi
      // dal puntatore con * otteniamo il puntato
      // e poi il cast a char
      char b = (char)*ptrToRam++;
      // se b non è rappresentabile 
      // stampo il punto ".".
      if ((b < 32) || (b > 126)) {
        Serial.print(".");
      } else {
        Serial.print(b);
      }
    }
    counter15--;
    counter15 = counter15 % 30;
  }
  Serial.println();
}

void reverseClear( uint8_t r, uint8_t c, uint8_t len) {
  for (int8_t col=c+len; col >c-1; col--) {
    lcd.setCursor(col, r);
    lcd.print(' ');
    delay(20);
  }
}

void letter(const char c, const uint8_t col) {
  
  for (char i=32; i<=c; i++) {
      lcd.setCursor(col, 0);
      lcd.print(i);
      delay(1);
  }
} 



void setup()
{
    Serial.begin(115200);
    
    lcd.begin(16, 2);
    // inizializza e stabilisce la lunghezza di textBuff 
    memset(textBuff, ' ', LEN_TEXT);
    myScroll.setText(textBuff);
    Serial.println(LEN_TEXT);

    // questi caratteri non sono in RAM
    letter( 'M', 4 );
    letter( 'A', 5 );
    letter( 'U', 6 );
    letter( 'R', 7 );
    letter( 'O', 8 );
    letter( 'T', 9 );
    letter( 'E', 10 );
    letter( 'C', 11 );
    delay(200);
    reverseClear(0, 4, 8);
    
    delay(100);
    lcd.setCursor(4, 0);
    lcd.print("MAUROTEC");
        
    showRam();
    uint32_t zero = 0;
    uint32_t uno = 1;
    if (0-1 < 0) {
      Serial.println("0-1 < 0");
    }
    if (zero-uno < zero) {
      Serial.println("zero-uno < zero");
    }
    Serial.println(zero-uno);

   
    millisOldTime = millis();
    Serial.println(myString);
  
} // end void setup()

uint8_t gCounter = 0;
uint32_t millisCont = 0;
void loop() {
    
    // tutte le string literal in sprintf sono in RAM.
    sprintf(textBuff, "%s %#9ul ",
              "[MauroTec Software], millis() vale",
              millis()
           );
    
    if (millis() - millisOldTime >= speedScroll) {
        millisOldTime = millis();
        gCounter++;
        if (gCounter == 70) 
            myScroll.restart(); // riavvio da capo lo scorrimento
        else if (gCounter == 150) {
            myScroll.clear(); //fermo lo scorrimento e resetto il buffer
            // lcd.setCursor(0, 1);
            // ferma lo scorrimento, resetta il buffer
            // e pulisce la riga.
            // lcd.print(myScroll.clear());
        }          
                    
        const char *scrollBuff = myScroll.doScroll();
        lcd.setCursor(0, 1);
        if (myScroll.isScroll()) {
            
            lcd.print(scrollBuff);
        } else {
            
            if (gCounter == 0) {
              
              // dopo un myScroll.clear() il buffer
              // è composto da 16 spazi e lo usiamo
              // per pulire la riga
              lcd.print(scrollBuff);
              lcd.setCursor(0, 1);
              // la string literal seguente è in RAM
              lcd.print("gCounter = ");
              lcd.print(gCounter);
            } else if (gCounter == 30) {
                myScroll.setScroll(true);
            } else if (gCounter == 190) {
              lcd.print(scrollBuff);
              lcd.setCursor(0, 1);
              // la string literal seguente NON è in RAM
              lcd.print(F("not Scroll text "));
            }
        }

    }
} // end void loop()





GND5VSDASCLSQWRTCDS1307+