#include <Wire.h>

#define PCF8574_ADDR (0x20) // Address of PCF8574 IC

#define ENCODER_CLK 2
#define ENCODER_DT  3
#define ENCODER_SW  4

int counter, lastCounter = 0;

void setup() {
  Serial.begin(9600);

  // Initialize encoder pins
  pinMode(ENCODER_CLK, INPUT);
  pinMode(ENCODER_DT, INPUT);
  pinMode(ENCODER_SW, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(ENCODER_CLK), readEncoder, FALLING);

  Wire.begin();

  if (!Wire.requestFrom(PCF8574_ADDR, 1)) {
    Serial.println("Chip not responding. Did you create wokwi-custom-chip.c.temp/.ts?");
    delay(500);
  } else {
    Serial.print("I²C initialized at address: 0x");
    Serial.println(PCF8574_ADDR, HEX);
    delay(500);
  }
}

void loop() {
  transmitCounter();

  if (digitalRead(ENCODER_SW) == LOW) {
    resetCounter();
  }
}

void transmitCounter()
{
  int currentCounter = getCounter();

  if (currentCounter != lastCounter) {
    lastCounter = currentCounter;

    Serial.print("Counter: ");
    Serial.println(currentCounter);

    switch (currentCounter) {
      case 0:
        // Turn off all ports
        transmit(0);
        break;
      case 1:
        // Turn on port P0
        transmit(B00000001);
        break;
      case 2:
        // Turn on port P1
        transmit(B00000010);
        break;
      case 3:
        // Turn on port P2
        transmit(B00000100);
        break;
      case 4:
        // Turn on port P3
        transmit(B00001000);
        break;
      case 5:
        // Turn on port P4
        transmit(B00010000);
        break;
      case 6:
        // Turn on port P5
        transmit(B00100000);
        break;
      case 7:
        // Turn on port P6
        transmit(B01000000);
        break;
      case 8:
        // Turn on port P7
        transmit(B10000000);
        break;
      case 9:
        // Turn on all ports
        transmit(B11111111);
        break;
    }
  }
}

void transmit(byte value) {
  // Start transmission to PCF8574 address
  Wire.beginTransmission(PCF8574_ADDR);
  Wire.write(value); // Send data to I²C
  Wire.endTransmission();
}

void readEncoder() {
  int dtValue = digitalRead(ENCODER_DT);

  if (dtValue == HIGH) {
    counter++; // Clockwise
  }

  if (dtValue == LOW) {
    counter--; // Counterclockwise
  }

  if (counter < 0) {
    counter = 9;
  }

  if (counter > 9) {
    counter = 0;
  }
}

int getCounter() {
  int result;
  // Get the counter value, disabling interrupts
  // This make sure readEncoder() doesn't change the value
  // while we're reading it
  noInterrupts();
  result = counter;
  interrupts();
  return result;
}

void resetCounter() {
  noInterrupts();
  counter = 0;
  interrupts();
  transmit(0);
}
PCF8574Breakout