Switch lcd1602 sketch to oled ssd1306 128x32 temperature controller

Iam beginner in arduino sketch ,
I try to write sketch based on attiny85 & lcd1602 its take 1 month :joy:.
Now i want switch to oled ssd1306 128x32 .
But i have trouble because diferent I2C .

This my sketch with lcd 1602 bit banging , maybe someone can help me build the sketch switch to oled with same function.

`#include <avr/io.h>
#include <util/delay.h>
#include <math.h>

// Pin definisi
#define SDA PB0
#define SCL PB2
#define ADC_PIN A3 // PB3 / ADC3
#define PWM_PIN PB4 // PWM manual
#define FAN_PIN PB1

// Konstanta NTC
#define R_FIXED 10000.0
#define R25 15000.0
#define BETA 3950.0
#define T0 298.15

// Hysteresis thresholds
#define HYSTERESIS_HIGH 50.1  // Batas aktifkan over-temp
#define HYSTERESIS_LOW  48.0   // Batas nonaktifkan over-temp

// Variabel global
float prevTemp = 25.0;
float smoothedTemp = 25.0;
bool overTemp = false;

// === Bit-banging I2C ===
void i2c_start() {
  digitalWrite(SDA, LOW);
  _delay_us(5);
  digitalWrite(SCL, LOW);
}

void i2c_stop() {
  digitalWrite(SDA, LOW);
  digitalWrite(SCL, HIGH);
  _delay_us(5);
  digitalWrite(SDA, HIGH);
  _delay_us(5);
}

void i2c_write(uint8_t data) {
  for (uint8_t i = 0; i < 8; i++) {
    digitalWrite(SDA, (data & 0x80));
    data <<= 1;
    digitalWrite(SCL, HIGH);
    _delay_us(5);
    digitalWrite(SCL, LOW);
  }
  pinMode(SDA, INPUT);
  digitalWrite(SCL, HIGH);
  _delay_us(5);
  digitalWrite(SCL, LOW);
  pinMode(SDA, OUTPUT);
}

// === LCD I2C ===
#define LCD_ADDR 0x27

void lcd_command(uint8_t cmd) {
  uint8_t hi = cmd & 0xF0, lo = (cmd << 4) & 0xF0;
  for (uint8_t i = 0; i < 2; i++) {
    uint8_t d = (i == 0) ? hi : lo;
    i2c_start();
    i2c_write(LCD_ADDR << 1);
    i2c_write(d | 0x0C);
    i2c_write(d | 0x08);
    i2c_stop();
  }
  _delay_ms(2);
}

void lcd_data(uint8_t chr) {
  uint8_t hi = chr & 0xF0, lo = (chr << 4) & 0xF0;
  for (uint8_t i = 0; i < 2; i++) {
    uint8_t d = (i == 0) ? hi : lo;
    i2c_start();
    i2c_write(LCD_ADDR << 1);
    i2c_write(d | 0x0D);
    i2c_write(d | 0x09);
    i2c_stop();
  }
  _delay_us(50);
}

void lcd_init() {
  _delay_ms(50);
  lcd_command(0x33);
  lcd_command(0x32);
  lcd_command(0x28);
  lcd_command(0x0C);
  lcd_command(0x06);
  lcd_command(0x01);
  _delay_ms(10);
}

void lcd_setCursor(uint8_t col, uint8_t row) {
  lcd_command(0x80 | (col + (row * 0x40)));
}

void lcd_print(const char* s) {
  while (*s) lcd_data(*s++);
}

void lcd_clear_row(uint8_t row) {
  lcd_setCursor(0, row);
  for (uint8_t i = 0; i < 16; i++) lcd_data(' ');
}

// === Suhu dari NTC ===
float readTemperature() {
  int adc = analogRead(ADC_PIN);
  float v = adc / 1023.0;
  float r = R_FIXED * (1.0 / v - 1.0);
  float invT = 1.0 / T0 + (1.0 / BETA) * log(r / R25);
  return (1.0 / invT) - 273.15;
}

// PWM manual dengan delay manual, ~1ms default period
void pwm_manual(float duty_percent, uint16_t period_us = 1000) {
  if (duty_percent < 0) duty_percent = 0;
  if (duty_percent > 100) duty_percent = 100;

  uint8_t duty = (uint8_t)(duty_percent * 2.55); // 0–255
  uint16_t delay_steps = period_us / 255;

  for (uint8_t i = 0; i < 255; i++) {
    if (i < duty) PORTB |= (1 << PWM_PIN);
    else PORTB &= ~(1 << PWM_PIN);

    for (uint16_t d = 0; d < delay_steps * 4; d++) { __asm__ __volatile__("nop"); }
  }
}

void splash_screen() {
  lcd_setCursor(0, 0);
  lcd_print(" INTELLIGENCE ");
  lcd_setCursor(0, 1);
  lcd_print("TEMP CONTROLLED");
  for (uint8_t i = 0; i < 35; i++) _delay_ms(100);
  lcd_command(0x01);
}

void setup() {
  pinMode(SDA, OUTPUT);
  pinMode(SCL, OUTPUT);
  pinMode(ADC_PIN, INPUT);
  pinMode(FAN_PIN, OUTPUT);
  pinMode(PWM_PIN, OUTPUT);
  digitalWrite(FAN_PIN, LOW);
  lcd_init();
  splash_screen();
}

void loop() {
  float temp = readTemperature();
  smoothedTemp = smoothedTemp * 0.5 + temp * 0.5;

  // Logika hysteresis
  if (smoothedTemp >= HYSTERESIS_HIGH) {
    overTemp = true;
  } else if (smoothedTemp <= HYSTERESIS_LOW) {
    overTemp = false;
  }

  float pwm = 0;
  if (overTemp) {
    pwm = 100;
    digitalWrite(FAN_PIN, HIGH);
  } else if (smoothedTemp >= 30 && smoothedTemp < HYSTERESIS_HIGH) {
    pwm = 25 + (smoothedTemp - 30) * (75.0 / 20.0);
    digitalWrite(FAN_PIN, LOW);
  } else {
    digitalWrite(FAN_PIN, LOW);
  }

  pwm_manual(pwm);

  // Baris 1
  char tbuf[10];
  dtostrf(smoothedTemp, 5, 1, tbuf);
  lcd_setCursor(0, 0);
  lcd_print("Temp: ");
  lcd_print(tbuf);
  lcd_print(" C ");

  // Baris 2 anti-flicker
  static bool lastOverTemp = false;
  static int lastPwmInt = -1;

  if (overTemp != lastOverTemp || (int)pwm != lastPwmInt) {
    lcd_clear_row(1);
    lcd_setCursor(0, 1);
    if (overTemp) {
      lcd_print("!! LIMIT WARNING ");
    } else {
      char pbuf[10];
      dtostrf(pwm, 5, 1, pbuf);
      lcd_print("PWM = ");
      lcd_print(pbuf);
      lcd_print(" % ");
    }
    lastOverTemp = overTemp;
    lastPwmInt = (int)pwm;
  }

  _delay_ms(250);
}`

Please, wrap your formatted code in a code block.

Cool. Do the same to post #1.

As you did before, start with a datasheet of your SSD1306

Edit post #1 and put the code in a <CODE> block.