ST7735 Menu item smooth scrolling

Look at the Bounce2 library. It does the button debouncing without using delay()...

#define SCR_WD   128
#define SCR_HT   160
#include <SPI.h>
#include <Adafruit_GFX.h>

#if (__STM32F1__) // bluepill
#define TFT_CS  PA2
#define TFT_DC  PA1
#define TFT_RST PA0
//#include <Arduino_ST7735_STM.h>
#else
#define TFT_CS        8
#define TFT_RST        7 // Or set to -1 and connect to Arduino RESET pin
#define TFT_DC         6
#include <Arduino_ST7735_Fast.h>
#endif

#include <Bounce2.h>

Arduino_ST7735 lcd = Arduino_ST7735(TFT_DC, TFT_RST, TFT_CS);
byte menuPos, menuScreen, markerPos, menuStartAt;
const char* const menu[12] PROGMEM  = {"Binary to Decimal", "Binary to Octal", "Binary to Hexa Deci", "Decimal to Binary", "Decimal to Ocatl", "Decimal to Hexa Deci", "Octal to Binary",
                                       "Octal to decimal", "Octal to Hexa Deci", "Hexa-Decimal to Binary", "Hexa-Decimal to Ocatl", "Hexa-Deci to Decimal"
                                      };
byte MENU_LENGTH =  sizeof(menu) / sizeof(menu[0]);
#define btnEnt 4
#define btnUp 3
#define btnDwn 2
#define MENU_ROW_HEIGHT 12
#define LCD_ROWS 12

Bounce2::Button buttonEnter = Bounce2::Button();
Bounce2::Button buttonUp = Bounce2::Button();
Bounce2::Button buttonDown = Bounce2::Button();
const int debounceTime = 10;

void setup() {
  Serial.begin(9600);
  //pinMode(btnUp, INPUT_PULLUP);
  //pinMode(btnDwn, INPUT_PULLUP);
  //pinMode(btnEnt, INPUT_PULLUP);
  buttonEnter.attach( btnEnt, INPUT_PULLUP );
  buttonEnter.interval(debounceTime);  // debounce time, ms
  buttonEnter.setPressedState(LOW); // INPUT_PULLUP means LOW == pressed
  buttonUp.attach( btnUp, INPUT_PULLUP );
  buttonUp.interval(debounceTime);  // debounce time, ms
  buttonUp.setPressedState(LOW); // INPUT_PULLUP means LOW == pressed
  buttonDown.attach( btnDwn, INPUT_PULLUP );
  buttonDown.interval(debounceTime);  // debounce time, ms
  buttonDown.setPressedState(LOW); // INPUT_PULLUP means LOW == pressed

  lcd.init();
  lcd.fillScreen(BLACK);
  delay(2000);
  showMenu();
}

void loop() {
  // update button state every time through loop
  buttonEnter.update();
  buttonUp.update();
  buttonDown.update;

  if (buttonDown.pressed()) {
    if (menuPos < MENU_LENGTH - 1) {
      menuPos++;
      if (menuPos - menuStartAt > 12 )
        menuStartAt++;
      showMenu();
    }
  }

  if (buttonUp.pressed()) {
    if (menuPos > 0) {
      menuPos--;
      if (menuPos - menuStartAt < 0 && menuStartAt != 0)
        menuStartAt--;
      showMenu();
    }
  }

  if (buttonEnter.pressed()) {
    Serial.print("Running test "); Serial.println(menuPos);
    switch ( menuPos ) {
      case  0: test0();   break;
      //case  1: test1();   break;
      //case  2: test2();   break;
      //case  3: test3();   break;
      //case  4: test4();   break;
      //case  5: test5();   break;
      //case  6: test6();   break;
      //case  7: test7();   break;
      //case  8: test8();   break;
      //case  9: test9();   break;
      //case 10: test10();  break;
      //case 11: test11();  break;
      //case 12: test12();  break;
    }
  }
}

void showMenu() {
  for (byte i = menuStartAt; i < (menuStartAt + LCD_ROWS); i++) {
    byte markerY = (i - menuStartAt) * MENU_ROW_HEIGHT;
    if (i == menuPos) {
      lcd.setTextColor(BLACK);
      lcd.fillRect(0, markerY, lcd.width(), MENU_ROW_HEIGHT, GREEN);
    }
    else {
      lcd.setTextColor(WHITE);
      lcd.fillRect(0, markerY, lcd.width(), MENU_ROW_HEIGHT, BLACK);
    }
    if (i >= MENU_LENGTH)
      continue;
    lcd.setCursor(3, markerY + 2);
    lcd.print((char*)pgm_read_word(&(menu[i])));
  }
}

void test0() {
  lcd.fillScreen(BLACK);
  lcd.setTextColor(WHITE);
  lcd.setCursor(1, 1);
  lcd.println(F("Waiting to \nregister sim \ncard"));
  delay(3000);
  showMenu();
}
1 Like