#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <MD_MAX72xx.h>
#include <IRremote.h>
// --- TFT ---
#define TFT_CS 5
#define TFT_DC 2
#define TFT_RST 4
#define TFT_MOSI 23
#define TFT_CLK 18
#define TFT_MISO 19
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
// --- MAX7219 ---
#define MAX7219_CS 15
#define MAX_DEVICES 4
MD_MAX72XX mx = MD_MAX72XX(MD_MAX72XX::FC16_HW, MAX7219_CS, MAX_DEVICES);
// --- Przyciski ---
#define BTN_LEFT 32
#define BTN_RIGHT 33
#define BTN_UP 25
#define BTN_DOWN 26
#define BTN_OK 27
// --- IR ---
#define IR_RECV_PIN 34
IRrecv irrecv(IR_RECV_PIN);
decode_results results;
// -------------------------
// Menu
enum MenuLevel { MAIN, GRA, GRACZE, PILOT, ADD_PLAYER };
MenuLevel currentMenu = MAIN;
int menuIndex = 0;
String menuItemsMain[] = {"GRA", "GRACZE", "PILOT"};
String menuItemsGra[] = {"501", "CRICKET"};
String menuItemsPilot[] = {"wyniki","gracz+","gracz-","gora","dol","lewo","prawo","ok","triple","double","popraw","cofnij","0","1","2","3","4","5","6","7","8","9"};
// gracze
String players[8];
bool selected[8];
int playerCount = 0;
int cursorAddIndex = 0;
String newName = "A"; // nick w trybie dodawania
// -------------------------
void setup() {
Serial.begin(115200);
tft.begin();
tft.setRotation(1);
tft.fillScreen(ILI9341_BLACK);
tft.setTextSize(2);
mx.begin();
mx.control(MD_MAX72XX::INTENSITY, 2);
pinMode(BTN_LEFT, INPUT_PULLUP);
pinMode(BTN_RIGHT, INPUT_PULLUP);
pinMode(BTN_UP, INPUT_PULLUP);
pinMode(BTN_DOWN, INPUT_PULLUP);
pinMode(BTN_OK, INPUT_PULLUP);
irrecv.enableIRIn();
drawMenu();
}
void loop() {
handleButtons();
if (irrecv.decode(&results)) {
Serial.print("IR: ");
Serial.println(results.value, HEX);
irrecv.resume();
}
}
void handleButtons() {
if (digitalRead(BTN_UP)==LOW) { menuUp(); delay(200);}
if (digitalRead(BTN_DOWN)==LOW) { menuDown(); delay(200);}
if (digitalRead(BTN_OK)==LOW) { menuSelect(); delay(200);}
if (digitalRead(BTN_LEFT)==LOW) { menuLeft(); delay(200);}
if (digitalRead(BTN_RIGHT)==LOW){ menuRight(); delay(200);}
}
// ------------------- Rysowanie menu
void drawMenu() {
tft.fillScreen(ILI9341_BLACK);
String *list;
int size;
int y=40;
switch(currentMenu) {
case MAIN: list=menuItemsMain; size=3; break;
case GRA: list=menuItemsGra; size=2; break;
case GRACZE:size=1+playerCount; break;
case PILOT: list=menuItemsPilot; size=sizeof(menuItemsPilot)/sizeof(menuItemsPilot[0]); break;
case ADD_PLAYER: drawAddPlayer(); return;
}
if (menuIndex<0) menuIndex=size-1;
if (menuIndex>=size) menuIndex=0;
for (int i=0;i<size;i++) {
tft.setCursor(10,y+i*30);
if (i==menuIndex) {
tft.setTextColor(ILI9341_YELLOW, ILI9341_BLACK);
if (currentMenu==GRACZE && i>0 && selected[i-1]) tft.print("> ["+players[i-1]+"]");
else if (currentMenu==GRACZE && i>0) tft.print("> "+players[i-1]);
else if (currentMenu==GRACZE && i==0) tft.print("> DODAJ");
else tft.print("> "+list[i]);
showOnMatrix((currentMenu==GRACZE && i>0)?players[i-1]:((currentMenu==GRACZE)?"DODAJ":list[i]));
} else {
tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
if (currentMenu==GRACZE && i>0 && selected[i-1]) tft.print(" ["+players[i-1]+"]");
else if (currentMenu==GRACZE && i>0) tft.print(" "+players[i-1]);
else if (currentMenu==GRACZE && i==0) tft.print(" DODAJ");
else tft.print(" "+list[i]);
}
}
}
void drawAddPlayer() {
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(20,60);
tft.setTextColor(ILI9341_YELLOW, ILI9341_BLACK);
tft.print("Nick: "+newName+"_");
showOnMatrix(newName);
}
// -------------------
void menuUp() {
if (currentMenu==ADD_PLAYER) {
char c=newName[cursorAddIndex];
if (c<'Z') c++; else c='A';
newName[cursorAddIndex]=c;
drawAddPlayer();
} else { menuIndex--; drawMenu(); }
}
void menuDown() {
if (currentMenu==ADD_PLAYER) {
char c=newName[cursorAddIndex];
if (c>'A') c--; else c='Z';
newName[cursorAddIndex]=c;
drawAddPlayer();
} else { menuIndex++; drawMenu(); }
}
void menuLeft() {
if (currentMenu==ADD_PLAYER && cursorAddIndex>0) cursorAddIndex--;
drawAddPlayer();
}
void menuRight() {
if (currentMenu==ADD_PLAYER) {
if (cursorAddIndex<9) {
cursorAddIndex++;
if (newName.length()<=cursorAddIndex) newName += "A";
}
}
drawAddPlayer();
}
void menuSelect() {
if (currentMenu==MAIN) {
if (menuIndex==0) { currentMenu=GRA; menuIndex=0; }
else if (menuIndex==1){ currentMenu=GRACZE; menuIndex=0; }
else { currentMenu=PILOT; menuIndex=0; }
drawMenu();
} else if (currentMenu==GRACZE) {
if (menuIndex==0) {
currentMenu=ADD_PLAYER;
newName="A";
cursorAddIndex=0;
drawAddPlayer();
} else {
int idx=menuIndex-1;
selected[idx]=!selected[idx];
drawMenu();
}
} else if (currentMenu==ADD_PLAYER) {
if (playerCount<8) {
players[playerCount]=newName;
selected[playerCount]=false;
playerCount++;
}
currentMenu=GRACZE; menuIndex=0; drawMenu();
} else {
Serial.println("Wybrano element: "+String(menuIndex));
}
}
// -------------------
void showOnMatrix(String text) {
mx.clear();
for (int i=0;i<text.length() && i<MAX_DEVICES;i++)
mx.setChar((MAX_DEVICES-1)-i, text[i]);
}