// ESP32 steuert eine touch table Matrix mit WS2816
// Anton Burger Design 2023
// Softwarestand: 18.4.2013
//-----------------------------------------------------------------
#include <WiFi.h>
#include <Wire.h>
#include <FastLED.h>
#include <WiFiManager.h>
// FASTLED
#define NUM_LEDS 16*6 /*the number of leds that will light. If */
#define DATA_PINA 13 // Connect to the data wires on the pixel strips
CRGB ledsA[NUM_LEDS]; // sets number of pixels that will light on each strip.
// OUTPUT CHIPS How many of the shift registers
const uint8_t numOfRegisterPinsOutput = 16;
#define DATA_PIN_74HC595  21 // Pin connected to DS of 74HC595
#define LATCH_PIN_74HC595 22 // Pin connected to STCP of 74HC595
#define CLOCK_PIN_74HC595 23 // Pin connected to SHCP of 74HC595
// INPUT CHIPS How many of the shift registers
const uint8_t numOfRegisterPinsInput = 16;
#define DATA_PIN_74HC165   5  // Pin connected to DS of 74HC165
#define LATCH_PIN_74HC165 18  // Pin connected to STCP of 74HC165
#define CLOCK_PIN_74HC165 19  // Pin connected to SHCP of 74HC165
// Hier wird der Schalterzustand gespeichert
bool tableRegister[numOfRegisterPinsOutput][numOfRegisterPinsInput];
#define NTP_SERVER     "pool.ntp.org"
#define UTC_OFFSET     0
#define UTC_OFFSET_DST 0
//---------------------------------------------------------------------------
void printLocalTime() {
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    Serial.println("Connection Err");
    return;
  }
  Serial.println(&timeinfo, "%H:%M:%S");
  Serial.println(&timeinfo, "%d/%m/%Y   %Z");
}
//---------------------------------------------------------------------------
//   SETUP
//---------------------------------------------------------------------------
void setup() {
  FastLED.addLeds<WS2812B, DATA_PINA, GRB>(ledsA, NUM_LEDS);
  
  pinMode(DATA_PIN_74HC595, INPUT);
  pinMode(CLOCK_PIN_74HC595, OUTPUT);
  pinMode(LATCH_PIN_74HC595, OUTPUT);
  pinMode(DATA_PIN_74HC165, INPUT);
  pinMode(CLOCK_PIN_74HC165, OUTPUT);
  pinMode(LATCH_PIN_74HC165, OUTPUT);
  
  Serial.begin(115200);
  WiFi.begin("Wokwi-GUEST", "", 6);
  while (WiFi.status() != WL_CONNECTED) {
    delay(250);
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  configTime(UTC_OFFSET, UTC_OFFSET_DST, NTP_SERVER);
  
  clearTableRegister();
 
}
//---------------------------------------------------------------------------
void fillStrip(const struct CRGB &color) {
  fill_solid(ledsA, NUM_LEDS+1, color); 
  FastLED.show();
}
//---------------------------------------------------------------------------
void writeStrip() {
  FastLED.show();
}
//---------------------------------------------------------------------------
void clearTableRegister() {
  for (int x=0; x <= numOfRegisterPinsOutput - 1; x++) { 
    for (int y=0; y <= numOfRegisterPinsInput - 1; y++) { 
      tableRegister[x][y] = false; 
    }
  }
}
//---------------------------------------------------------------------------
void serialPrintRegisters() {
  for (int x=0; x <= numOfRegisterPinsOutput - 1;  x++) { 
    for (int y=0; y <= numOfRegisterPinsInput - 1;  y++) { 
      Serial.print(tableRegister[x][y]);
    }
    Serial.println();
  }
  Serial.println();
}
//---------------------------------------------------------------------------
void readIrSwitches() { 
  for (int i=0; i <= numOfRegisterPinsOutput - 1;  i++) {     
    writeXTo74HC595(i);                         // Setzt den entsprechenden Pin in X Richtung
    readYFrom74HC169(i*numOfRegisterPinsInput); // Liest die gesetzen Pins in das tableRegister ein
  } 
}
//---------------------------------------------------------------------------
void writeXTo74HC595(int pin) {
  // Set and display registersOutput
  digitalWrite(LATCH_PIN_74HC595, LOW);
  for (int i=0; i <= numOfRegisterPinsOutput-1; i++) {
    digitalWrite(CLOCK_PIN_74HC595, LOW);    
    if(i==pin)
      digitalWrite(DATA_PIN_74HC595, true);
    else
      digitalWrite(DATA_PIN_74HC595, false);
    digitalWrite(CLOCK_PIN_74HC595, HIGH);
  }
  digitalWrite(LATCH_PIN_74HC595, HIGH);
}
//---------------------------------------------------------------------------
void readYFrom74HC169(int tableRegisterAdress) {
  // Step 1: Sample
  digitalWrite(LATCH_PIN_74HC165, LOW);
  digitalWrite(LATCH_PIN_74HC165, HIGH);
  
  // Step 2: Shift
  for (int i=0; i <= numOfRegisterPinsInput-1; i++) {
    tableRegister[tableRegisterAdress][i] = digitalRead(DATA_PIN_74HC165);
    digitalWrite(CLOCK_PIN_74HC165, HIGH);   // Shift out the next bit
    digitalWrite(CLOCK_PIN_74HC165, LOW);
  }
}
//---------------------------------------------------------------------------
void loop() {
  printLocalTime();
  fillStrip( CRGB::Blue);
  readIrSwitches();
  serialPrintRegisters();
  delay(1000);
  fillStrip( CRGB::Red);
}