#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Preferences.h>
#include <vector>
// --- KONFİGÜRASYON ---
const int NUM_OUT_CHIPS = 8;
const int NUM_IN_CHIPS = 36;
const int TOTAL_OUT = NUM_OUT_CHIPS * 8;
const int TOTAL_IN = NUM_IN_CHIPS * 8;
const int NUM_SLOTS = 10;
const size_t MATRIX_SIZE = TOTAL_OUT * NUM_IN_CHIPS;
LiquidCrystal_I2C lcd(0x27, 20, 4);
Preferences prefs;
#define ENCODER_CLK 34
#define ENCODER_DT 32
#define ENCODER_SW 33
#define OUT_DATA_PIN 12
#define OUT_LATCH_PIN 14
#define OUT_CLOCK_PIN 27
#define IN_DATA_PIN 2
#define IN_CLOCK_PIN 17
#define IN_LATCH_PIN 4
uint8_t fullMatrix[MATRIX_SIZE];
int selectedSlot = 0;
int lastSelectedSlot = -1;
int lastClk = HIGH;
//String slotNames[NUM_SLOTS] = {"P1", "P2", "P3", "P4", "P5", "P6", "P7", "P8", "P9", "P10"};
String slotNames[NUM_SLOTS] = {
"AKINCI_TURKIYE", "AKINCI_GLOBAL", "TB2_TURKIYE",
"TB2_GLOBAL", "TB3_TURKIYE", "TB3_GLOBAL", "KIZILELMA",
"KALKAN", "KEMANKES", "MINI_IHA"
};
// --- EKRAN YÖNETİMİ ---
void showMainMenu() {
if (selectedSlot != lastSelectedSlot) {
lcd.clear();
lcd.setCursor(0, 0); lcd.print(">> KABLO SECIMI <<");
lcd.setCursor(0, 1); lcd.print(String(selectedSlot + 1) + ": " + slotNames[selectedSlot]);
lcd.setCursor(0, 3); lcd.print("CEVIR:Gez BAS:Sec");
lastSelectedSlot = selectedSlot;
}
}
void drawSubMenu(int opt, int lastOpt) {
if (opt != lastOpt) {
lcd.clear();
lcd.setCursor(0, 0); lcd.print("SLOT: " + slotNames[selectedSlot]);
lcd.setCursor(0, 1); lcd.print((opt == 0 ? "> " : " ") + String("TEST ET"));
lcd.setCursor(0, 2); lcd.print((opt == 1 ? "> " : " ") + String("YENI OGRET"));
lcd.setCursor(0, 3); lcd.print((opt == 2 ? "> " : " ") + String("GERI DON"));
}
}
// --- CORE TARAMA MANTIĞI (Düzeltilmiş Bit Sırası) ---
void scanCurrentHarness(uint8_t* buffer) {
for (int i = 0; i < TOTAL_OUT; i++) {
digitalWrite(OUT_LATCH_PIN, LOW);
// Çıkışları MSBFIRST ile göndererek bit kaymasını önlüyoruz
for (int c = NUM_OUT_CHIPS - 1; c >= 0; c--) {
uint8_t val = (i / 8 == c) ? (1 << (i % 8)) : 0;
shiftOut(OUT_DATA_PIN, OUT_CLOCK_PIN, MSBFIRST, val);
}
digitalWrite(OUT_LATCH_PIN, HIGH);
delay(35); // 1-10 metre kablo gecikme payı
digitalWrite(IN_LATCH_PIN, LOW);
delayMicroseconds(15);
digitalWrite(IN_LATCH_PIN, HIGH);
for (int c = 0; c < NUM_IN_CHIPS; c++) {
// Donanımsal 2-3 görme hatasını buradaki MSBFIRST/LSBFIRST değişimi çözer
// Eğer hala kayma varsa burayı LSBFIRST yapıp tekrar dene
buffer[(i * NUM_IN_CHIPS) + c] = shiftIn(IN_DATA_PIN, IN_CLOCK_PIN, MSBFIRST);
}
}
}
// --- KAYIT VE TEST ---
void learnAndSave(int slot) {
lcd.clear(); lcd.print("OGRENIYOR...");
scanCurrentHarness(fullMatrix);
prefs.begin("harness", false);
prefs.putBytes(("slot" + String(slot)).c_str(), fullMatrix, MATRIX_SIZE);
prefs.end();
lcd.clear(); lcd.print("HAFIZAYA ALINDI!");
delay(1500);
}
void runTest(int slot) {
lcd.clear(); lcd.print("HAFIZA OKUNUYOR...");
prefs.begin("harness", true);
prefs.getBytes(("slot" + String(slot)).c_str(), fullMatrix, MATRIX_SIZE);
prefs.end();
std::vector<String> errors;
uint8_t currentScan[MATRIX_SIZE];
lcd.clear(); lcd.print("TEST EDIYOR...");
scanCurrentHarness(currentScan);
for (int i = 0; i < TOTAL_OUT; i++) {
for (int c = 0; c < NUM_IN_CHIPS; c++) {
uint8_t actual = currentScan[(i * NUM_IN_CHIPS) + c];
uint8_t expected = fullMatrix[(i * NUM_IN_CHIPS) + c];
if (actual != expected) {
for (int b = 0; b < 8; b++) {
bool expBit = bitRead(expected, b);
bool actBit = bitRead(actual, b);
int pIn = (c * 8) + b + 1;
if (expBit && !actBit) errors.push_back(String(i+1) + "-" + String(pIn) + " Eksik");
if (!expBit && actBit) errors.push_back(String(i+1) + "-" + String(pIn) + " KisaD");
}
}
}
}
if (errors.size() == 0) {
lcd.clear(); lcd.print("DURUM: OK!");
while(digitalRead(ENCODER_SW) == HIGH); delay(300);
} else {
showErrorScroll(errors);
}
}
void showErrorScroll(std::vector<String>& errors) {
int pos = 0, oldPos = -1;
while(true) {
if (pos != oldPos) {
lcd.clear();
lcd.setCursor(0, 0); lcd.print("Hata:" + String(errors.size()) + " [BAS:CIK]");
for (int i = 0; i < 3; i++) {
if (pos + i < errors.size()) {
lcd.setCursor(0, i + 1);
lcd.print(errors[pos + i]);
}
}
oldPos = pos;
}
int clk = digitalRead(ENCODER_CLK);
if (clk != lastClk && clk == LOW) {
if (digitalRead(ENCODER_DT) != clk) { if (pos < (int)errors.size() - 1) pos++; }
else { if (pos > 0) pos--; }
}
lastClk = clk;
if (digitalRead(ENCODER_SW) == LOW) { delay(300); break; }
delay(1);
}
}
void handleSelectionMenu() {
int menuOption = 0, lastMenuOption = -1;
while (true) {
drawSubMenu(menuOption, lastMenuOption);
lastMenuOption = menuOption;
int clkVal = digitalRead(ENCODER_CLK);
if (clkVal != lastClk && clkVal == LOW) {
if (digitalRead(ENCODER_DT) != clkVal) menuOption++; else menuOption--;
if (menuOption > 2) menuOption = 0; if (menuOption < 0) menuOption = 2;
}
lastClk = clkVal;
if (digitalRead(ENCODER_SW) == LOW) {
delay(300);
if (menuOption == 0) runTest(selectedSlot);
else if (menuOption == 1) learnAndSave(selectedSlot);
else if (menuOption == 2) break;
lastMenuOption = -1;
}
delay(1);
}
}
void setup() {
Serial.begin(115200);
lcd.init(); lcd.backlight();
pinMode(ENCODER_CLK, INPUT_PULLUP); pinMode(ENCODER_DT, INPUT_PULLUP); pinMode(ENCODER_SW, INPUT_PULLUP);
pinMode(OUT_DATA_PIN, OUTPUT); pinMode(OUT_LATCH_PIN, OUTPUT); pinMode(OUT_CLOCK_PIN, OUTPUT);
pinMode(IN_DATA_PIN, INPUT); pinMode(IN_CLOCK_PIN, OUTPUT); pinMode(IN_LATCH_PIN, OUTPUT);
digitalWrite(IN_LATCH_PIN, HIGH);
lcd.print("SISTEM HAZIR");
delay(1000);
}
void loop() {
showMainMenu();
int clkVal = digitalRead(ENCODER_CLK);
if (clkVal != lastClk && clkVal == LOW) {
if (digitalRead(ENCODER_DT) != clkVal) selectedSlot++; else selectedSlot--;
if (selectedSlot >= NUM_SLOTS) selectedSlot = 0;
if (selectedSlot < 0) selectedSlot = NUM_SLOTS - 1;
}
lastClk = clkVal;
if (digitalRead(ENCODER_SW) == LOW) { delay(300); handleSelectionMenu(); lastSelectedSlot = -1; }
delay(1);
}1
8
4
5