#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h> // SH1106 (1.3" OLED) sürücüsü
// --- KONFİGÜRASYON ---
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// ESP32-S3 Pin Atamaları
const int PIN_595_DATA = 2;
const int PIN_CLOCK = 3;
const int PIN_595_LATCH = 4;
const int PIN_165_LOAD = 5;
const int PIN_165_DATA = 6;
const int PIN_BUTTON = 7;
const int I2C_SDA = 8;
const int I2C_SCL = 9;
// UI Sabitleri
const int OUT_X = 25;
const int IN_X = 95;
const int BOX_W = 4;
const int EYE_RADIUS = 15;
const int PUPIL_RADIUS = 5;
const int EYE_SEP = 40;
// Fonksiyonlar
void drawStaticUI();
void performTest();
void animateEyes();
void drawEyes(int pupilOffset, bool open);
void setup() {
Serial.begin(115200);
// ESP32-S3 I2C Başlatma
Wire.begin(I2C_SDA, I2C_SCL);
// SH1106 Başlatma
if(!display.begin(SCREEN_ADDRESS, true)) {
Serial.println("OLED Bulunamadi!");
for(;;);
}
// AÇILIŞ ŞOVU (Hızlandırılmış)
animateEyes();
pinMode(PIN_595_DATA, OUTPUT);
pinMode(PIN_595_LATCH, OUTPUT);
pinMode(PIN_CLOCK, OUTPUT);
pinMode(PIN_165_LOAD, OUTPUT);
pinMode(PIN_165_DATA, INPUT);
pinMode(PIN_BUTTON, INPUT_PULLUP);
display.clearDisplay();
drawStaticUI();
}
void loop() {
if (digitalRead(PIN_BUTTON) == LOW) {
delay(50);
if (digitalRead(PIN_BUTTON) == LOW) {
performTest();
while(digitalRead(PIN_BUTTON) == LOW);
}
}
}
// --- GÖZ ANİMASYONU ---
void drawEyes(int pupilOffset, bool open) {
int centerX = SCREEN_WIDTH / 2;
int centerY = SCREEN_HEIGHT / 2;
display.clearDisplay();
if (open) {
display.fillCircle(centerX - EYE_SEP/2, centerY, EYE_RADIUS, SH110X_WHITE);
display.fillCircle(centerX - EYE_SEP/2 + pupilOffset, centerY, PUPIL_RADIUS, SH110X_BLACK);
display.fillCircle(centerX + EYE_SEP/2, centerY, EYE_RADIUS, SH110X_WHITE);
display.fillCircle(centerX + EYE_SEP/2 + pupilOffset, centerY, PUPIL_RADIUS, SH110X_BLACK);
} else {
display.drawLine(centerX - EYE_SEP/2 - EYE_RADIUS, centerY, centerX - EYE_SEP/2 + EYE_RADIUS, centerY, SH110X_WHITE);
display.drawLine(centerX + EYE_SEP/2 - EYE_RADIUS, centerY, centerX + EYE_SEP/2 + EYE_RADIUS, centerY, SH110X_WHITE);
}
display.display();
}
void animateEyes() {
drawEyes(0, false); delay(300);
drawEyes(0, true); delay(200);
for(int i=0; i<2; i++){
drawEyes(0, false); delay(50);
drawEyes(0, true); delay(100);
}
delay(150);
drawEyes(8, true); delay(350);
drawEyes(-8, true); delay(350);
drawEyes(0, true); delay(250);
drawEyes(0, false); delay(300);
}
// --- TEST ARAYÜZÜ ---
void drawStaticUI() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
display.setCursor(28, 0);
display.println("CABLE TESTER");
display.drawLine(0, 9, 128, 9, SH110X_WHITE);
display.setCursor(OUT_X - 5, 12); display.print("OUT");
display.setCursor(IN_X, 12); display.print("IN");
for(int i=0; i<8; i++) {
int y = 21 + (i * 4);
display.drawRect(OUT_X, y, BOX_W, BOX_W, SH110X_WHITE);
display.drawRect(IN_X, y, BOX_W, BOX_W, SH110X_WHITE);
}
display.display();
}
void performTest() {
drawStaticUI();
bool isError = false;
for (int i = 0; i < 8; i++) {
uint8_t send_val = (1 << i);
digitalWrite(PIN_595_LATCH, LOW);
shiftOut(PIN_595_DATA, PIN_CLOCK, MSBFIRST, send_val);
digitalWrite(PIN_595_LATCH, HIGH);
delayMicroseconds(60);
digitalWrite(PIN_165_LOAD, LOW);
delayMicroseconds(5);
digitalWrite(PIN_165_LOAD, HIGH);
uint8_t received = shiftIn(PIN_165_DATA, PIN_CLOCK, MSBFIRST);
int ySrc = 23 + (i * 4);
if (received == send_val) {
display.drawLine(OUT_X + BOX_W, ySrc, IN_X, ySrc, SH110X_WHITE);
}
else if (received == 0) {
display.fillRect(OUT_X, ySrc - 2, BOX_W, BOX_W, SH110X_WHITE); // KOPUK
isError = true;
}
else {
isError = true;
if (__builtin_popcount(received) > 1) {
display.setCursor(OUT_X - 10, ySrc - 3);
display.print("S"); // SHORT
}
for (int b = 0; b < 8; b++) {
if (bitRead(received, b)) {
int yDest = 23 + (b * 4);
display.drawLine(OUT_X + BOX_W, ySrc, IN_X, yDest, SH110X_WHITE);
}
}
}
display.display();
delay(40);
}
// Alt Sonuç Bandı (Y: 55)
display.fillRect(0, 55, 128, 9, SH110X_BLACK);
display.setTextSize(1);
if (!isError) {
display.setCursor(55, 56); display.print("PASS");
} else {
display.setCursor(52, 56); display.print("FAIL");
}
display.display();
}