#include <Wire.h>
#include <PCF8575.h>
#include <Adafruit_NeoPixel.h>
#include "Config.ino"

#define AMOUNTOFPORTS 8 // currently max 16 ports are supported
#define EXPANDER1ADDRESS 0x21 // address of expander 1

PCF8575 expander1(EXPANDER1ADDRESS);
uint8_t portStates[AMOUNTOFPORTS];
uint8_t lastStates[AMOUNTOFPORTS] = {0};
byte number=0;

extern Adafruit_NeoPixel* pixels;

void setup() {
  Serial.begin(9600);
  Serial.println("Starte 16-Port IO Erweiterung...");
  //Set UP 12C Communication
  Wire.begin();
  for (byte adress=8; adress<120; adress++)
  {
    Wire.beginTransmission(adress);
    if (Wire.endTransmission()==0)
    {
      Serial.print(number+1);
      Serial.print(". Device: 0x");
      Serial.println(adress, HEX);
      number++;
    }
  }
  Serial.print (number, DEC);
  Serial.println (" device(s) found.");
  //Setup CPF Expander
  
  Serial.print("Expander 1 at ");
    Serial.print(EXPANDER1ADDRESS,HEX);
  if (!expander1.begin())
  {
    Serial.println(" could not initialize...");
  }
  if (!expander1.isConnected())
  {
    Serial.println(" => not connected");
  }
  else
  {
    Serial.println(" => connected!!");
  }
    
  //Setup NeoPixel
  NeoPixel_init(AMOUNTOFPORTS); // Initialisierung der NeoPixel
    for (uint8_t i = 0; i < AMOUNTOFPORTS; i++) {
      portStates[i] = 0;
  lastStates[i] = 0;
  pixels->setPixelColor(i, pixels->Color(0, 0, 0)); // aus
  };
  pixels->show();

  Serial.println("Setup End...");
}

void loop() {
  // Erst 16 Ports aus PCF8575 einlesen
  for (uint8_t i = 0; i < AMOUNTOFPORTS; i++) {
    portStates[i] = expander1.read(i);
  }
  
  for (uint8_t i = 0; i < AMOUNTOFPORTS; i++) {
    if (portStates[i] != lastStates[i]) {
      // Ausgabe: geänderte Ports melden
      Serial.print("Pin ");
      Serial.print(i);
      Serial.print(" hat sich geändert -> ");
      Serial.println(portStates[i]);
      lastStates[i] = portStates[i];
    }
    // LED aktualisieren
    if (portStates[i] == 0) {
      pixels->setPixelColor(i, pixels->Color(0, 150, 0)); // grün
    } else {
      bool globalBlinkState = (millis() / BLINK_INTERVAL) % 2;
      if (globalBlinkState) {
        pixels->setPixelColor(i, pixels->Color(150, 0, 0)); // rot
      } else {
        pixels->setPixelColor(i, pixels->Color(0, 0, 0)); // aus
      }
    }
  }
  pixels->show();
  delay(50);
}