#include <Wire.h>
#define SCREEN_ADDRESS 0x3C // SSD1306 I2C adresi (0x3C veya 0x3D)
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
// Kontrol byte tanımları
#define CONTROL_COMMAND 0x00
#define CONTROL_DATA 0x40
void sendCommand(uint8_t command) {
Wire.beginTransmission(SCREEN_ADDRESS);
Wire.write(CONTROL_COMMAND);
Wire.write(command);
Wire.endTransmission();
}
void sendData(uint8_t data) {
Wire.beginTransmission(SCREEN_ADDRESS);
Wire.write(CONTROL_DATA);
Wire.write(data);
Wire.endTransmission();
}
void initializeDisplay() {
// I2C iletişimini başlat
Wire.begin();
// Temel başlatma komutları
sendCommand(0xAE); // Display OFF
sendCommand(0xD5); // Set Display Clock Divide
sendCommand(0x80); // Önerilen değer
sendCommand(0xA8); // Set Multiplex Ratio
sendCommand(0x3F); // 64 satır
sendCommand(0xD3); // Set Display Offset
sendCommand(0x00); // Offset yok
sendCommand(0x40); // Set Start Line
sendCommand(0x8D); // Charge Pump
sendCommand(0x14); // Enable Charge Pump
sendCommand(0x20); // Memory Mode
sendCommand(0x00); // Horizontal Addressing Mode
sendCommand(0xA1); // Segment Remap (0xA1 for 128-0)
sendCommand(0xC8); // COM Output Scan Direction (64-0)
sendCommand(0xDA); // Set COM Pins
sendCommand(0x12); // Alternative COM Pin Configuration
sendCommand(0x81); // Set Contrast Control
sendCommand(0xCF); // Contrast değeri
sendCommand(0xD9); // Set Pre-Charge Period
sendCommand(0xF1); // Önerilen değer
sendCommand(0xDB); // Set VCOMH Deselect Level
sendCommand(0x40); // Önerilen değer
sendCommand(0xA4); // Entire Display ON (RAM içeriğini göster)
sendCommand(0xA6); // Normal Display (0xA6) / Inverse (0xA7)
sendCommand(0xAF); // Display ON
}
void clearScreen() {
// Tüm sayfaları (0-7) ve sütunları (0-127) temizle
for(uint8_t page = 0; page < 8; page++) {
sendCommand(0xB0 | page); // Sayfa adresi
sendCommand(0x00); // Düşük sütun adresi
sendCommand(0x10); // Yüksek sütun adresi
for(uint8_t col = 0; col < 128; col++) {
sendData(0x00); // Tüm pikselleri kapat
}
}
}
void drawPixel(uint8_t x, uint8_t y) {
if(x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) return;
uint8_t page = y / 8;
uint8_t bit_mask = 1 << (y % 8);
sendCommand(0xB0 | page); // Sayfa adresi
sendCommand(0x00 | (x & 0x0F)); // Düşük sütun adresi
sendCommand(0x10 | (x >> 4)); // Yüksek sütun adresi
Wire.beginTransmission(SCREEN_ADDRESS);
Wire.write(CONTROL_DATA);
Wire.write(bit_mask);
Wire.endTransmission();
}
void clearPixel(uint8_t x, uint8_t y) {
if(x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) return;
uint8_t page = y / 8;
uint8_t bit_mask = 1 << (y % 8);
sendCommand(0xB0 | page); // Sayfa adresi
sendCommand(0x00 | (x & 0x0F)); // Düşük sütun adresi
sendCommand(0x10 | (x >> 4)); // Yüksek sütun adresi
Wire.beginTransmission(SCREEN_ADDRESS);
Wire.write(CONTROL_DATA);
Wire.write(0);
Wire.endTransmission();
}
uint8_t ballX = 64;
uint8_t ballY = 32;
int8_t ballSpeedX = 1;
int8_t ballSpeedY = 1;
uint8_t paddleY = 56;
void updateGame() {
// Top hareketi
ballX += ballSpeedX;
ballY += ballSpeedY;
// Duvarlardan sekme
if(ballX <= 0 || ballX >= 127) ballSpeedX = -ballSpeedX;
ballSpeedY = -1 * ballSpeedY;
if(ballY <= 0 || ballSpeedY;
// Paddle çarpışma kontrolü
if(ballY >= 56 && ballY <= 60) {
if(ballX >= paddleY && ballX <= paddleY+20) {
ballSpeedY = -1 * ballSpeedY;
}
}
}
void drawGame() {
clearScreen();
// Paddle çiz
for(uint8_t i = 0; i < 20; i++) {
drawPixel(paddleY + i, 60);
}
// Top çiz
drawPixel(ballX, ballY);
}
void setup() {
initializeDisplay();
clearScreen();
}
void loop() {
updateGame();
drawGame();
delay(50);
}