Hey everyone, I recently made a menu system using a TFT display and a teensy with a Rotary Knob. My code currently works however it's very hardcoded. I can't seem to find a way to remove the switch statement in drawMenuItems. I feel like I should be able to run it without that and be able to put all my menu data in arrays but can't seem to figure out how. Any help is appreciated.
#include <SdFat.h>
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#include <SPI.h>
#include "EncoderTool.h"
#include <vector>
using namespace EncoderTool;
// Encoder encoder;
PolledEncoder encoder;
// TIMER MODULE
const char *chapterSelect[] = {"Chapter 1", "Chapter 2", "Chapter 3", "Chapter 4", "Chapter 5", "Chapter 6", "Chapter 7", "Chapter 8", "Chapter 9", "Chapter 10", "Chapter 11"};
const int chapterSelectLength = 11;
const char *chapter1[] = {"Level 1", "Level 2", "Level 3", "Level 4", "Level 5", "Level 6", "Level 7", "Level 8"};
const int chapter1Length = 8;
const char *chapter2[] = {"Level 1", "Level 2", "Level 3", "Level 4"};
const int chapter2Length = 4;
const char *chapter3[] = {"Level 1", "Level 2", "Level 3", "Level 4", "Level 5"};
const int chapter3Length = 5;
const int menuWidth = 240;
const int menuHeight = 240;
const int menuTitlePadding = 6;
const int menuItemSize = 3;
const int menuTitleSize = 4;
const int menuItemPadding = 16;
const int maxMenuItems = 5;
int menuCurrentIndex = 0;
int minMenuItem = 0;
int menuCurrentIndexItems = 11;
int currentMenu = 0;
int chapterSelected = -1;
const char **menu = chapterSelect;
constexpr uint8_t A = 3, B = 4, Btn = 2; // pins
#define TFT_CS 10
#define TFT_RST 29 // Or set to -1 and connect to Arduino RESET pin
#define TFT_DC 30
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
// END TIMER MODULE
void drawTitle(String text, uint16_t color)
{
// Background
tft.drawRect(0, 0, menuWidth, menuTitleSize * 8 + menuTitlePadding * 2, 0x530f);
tft.fillRect(0, 0, menuWidth, menuTitleSize * 8 + menuTitlePadding * 2, 0x530f);
int x = (240 - (text.length() * menuTitleSize * 6)) / 2; // Center Title
tft.setCursor(x, menuTitlePadding);
tft.setTextColor(color);
tft.setTextWrap(false);
tft.setTextSize(menuTitleSize);
tft.print(text);
}
void drawMenuItems(int selected)
{
int numberOfItems;
switch (chapterSelected)
{
case -1:
menu = chapterSelect;
numberOfItems = chapterSelectLength;
break;
case 0:
menu = chapter1;
numberOfItems = chapter1Length;
break;
case 1:
menu = chapter2;
numberOfItems = chapter2Length;
break;
case 2:
menu = chapter3;
numberOfItems = chapter3Length;
break;
default:
break;
}
// Title
if (selected == 0)
{
drawTitle("Chapter", ST77XX_WHITE);
}
// If we hit the high end
if (selected >= numberOfItems)
{
Serial.println(selected);
encoder.setValue(numberOfItems - 1);
menuCurrentIndex = numberOfItems - 1;
Serial.println("NO MORE");
return;
}
// If we hit the low end
if (selected < 0)
{
encoder.setValue(0);
menuCurrentIndex = 0;
Serial.println("TOO LOW");
return;
}
// If we are at the bottom but have more items
if (selected > maxMenuItems)
{
Serial.println("MAX HIT");
minMenuItem = selected - maxMenuItems;
Serial.print("MinMenuItem: ");
Serial.println(minMenuItem);
}
else
{
minMenuItem = 0;
}
int menuIndex = 0;
for (uint8_t i = minMenuItem; i < numberOfItems; i++)
{
Serial.println(i);
int yBg = ((menuTitleSize * 8) + (menuTitlePadding * 2) + ((menuItemSize * 8) * menuIndex)) + (menuItemPadding / 2 * (menuIndex + 1)) - menuItemPadding / 2;
if (i == selected)
{
tft.drawRect(0, yBg, menuWidth, (menuItemSize * 8) + menuItemPadding - 4, ST77XX_BLUE);
tft.fillRect(0, yBg, menuWidth, (menuItemSize * 8) + menuItemPadding - 4, ST77XX_BLUE);
}
else
{
tft.drawRect(0, yBg, menuWidth, (menuItemSize * 8) + menuItemPadding - 4, ST77XX_BLACK);
tft.fillRect(0, yBg, menuWidth, (menuItemSize * 8) + menuItemPadding - 4, ST77XX_BLACK);
}
int y = ((menuTitleSize * 8) + (menuTitlePadding * 2) + ((menuItemSize * 8) * menuIndex)) + menuItemPadding / 2 * (menuIndex + 1);
tft.setCursor(5, y);
tft.setTextColor(ST77XX_WHITE);
tft.setTextWrap(false);
tft.setTextSize(menuItemSize);
tft.print(menu[i]);
menuIndex++;
}
}
void updateMenu(int value, int delta)
{
if (encoder.valueChanged()) // do we have a new value?
{
if (encoder.getValue() > menuCurrentIndex)
{
menuCurrentIndex++;
}
else
{
menuCurrentIndex--;
}
Serial.print("Encoder at before: ");
Serial.println(encoder.getValue());
drawMenuItems(menuCurrentIndex);
Serial.print("Encoder at after: ");
Serial.println(encoder.getValue());
}
}
void menuSelect(int state)
{
if (state == LOW)
{
currentMenu = 1;
chapterSelected = menuCurrentIndex;
tft.fillScreen(ST77XX_BLACK);
drawMenuItems(0);
Serial.println("SELECTED: ");
Serial.print(menuCurrentIndex);
}
Serial.print("Current button state: ");
Serial.println(state == LOW ? "pressed" : "released");
}
void setup(void)
{
Serial.begin(9600);
Serial.println("Initialized");
// TIMER SETUP
tft.init(menuWidth, menuHeight); // Init ST7789 240x240
tft.fillScreen(ST77XX_BLACK);
encoder.begin(3, 4, 2);
encoder.attachCallback(updateMenu);
encoder.attachButtonCallback(menuSelect);
// END TIMER SETUP
Serial.println("done");
drawMenuItems(0);
}
void loop()
{
encoder.tick();
}