// Arduino + Shift Register Help needed
// https://forum.arduino.cc/t/arduino-shift-register-help-needed/1323488


// Pin connected to ST_CP of 74HC595/164
int latchPin = 8;
// Pin connected to SH_CP of 74HC595/164
int clockPin = 12;
// Pin connected to DS of 74HC595/164
int dataPin = 11;
// Clear 164 output
int Clear = 9;

// holders for information you're going to pass to shifting function
byte dataRED;
byte dataGREEN;
byte dataYELLOW;

// Data to FGC Controller
byte dataToFGCU1;
byte dataToFGCU2;
byte dataToFGCU3;
byte dataArrayToFGC[4];

// Switches
enum : uint8_t {U1, U2, U3};  // U1 = 0, U2 = 1, U3 = 3
const int U_SW[][8] = {
  { 7,  6,  5,  4,  3,  2, 22, 23}, // dataArrayYELLOW
  {24, 25, 26, 27, 28, 29, 30, 31}, // dataArrayGREEN
  {32, 33, 34, 35, 36, 37, 38, 39}  // dataArrayRED
};

// Switches to binary/hex converter
int bitVal;
String stringBit;
String stringBinary;
long binaryNumber;
int decimalNumber;

void setup()
{
  // set pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);
  digitalWrite(latchPin, LOW);
  pinMode(Clear, OUTPUT);
  digitalWrite(Clear, LOW); // Set low to sett 164 to LOW out. Set HIGH to receiver data.

  dataArrayToFGC[0] = 0x00;   // U1
  dataArrayToFGC[1] = 0x00;   // U2
  dataArrayToFGC[2] = 0x00;   // U3


  Serial.begin(115200);
}


void loop()
{
  dataArrayToFGC[U1] = switchesValue(U1);
  Serial.print("U1 data: ");
  Serial.print(dataArrayToFGC[U1], HEX);
  dataArrayToFGC[U2] = switchesValue(U2);
  Serial.print("  ");
  Serial.print("U2 data: ");
  Serial.print(dataArrayToFGC[U2], HEX);
  dataArrayToFGC[U3] = switchesValue(U3);
  Serial.print("  ");
  Serial.print("U3 data: ");
  Serial.println(dataArrayToFGC[U3], HEX);

  // set latch pin Low
  digitalWrite(latchPin, LOW);
  digitalWrite(Clear, HIGH);

  // send data to 595/
  shiftOut(dataPin, clockPin, dataArrayToFGC[U1]);    // Yellow Lights
  shiftOut(dataPin, clockPin, dataArrayToFGC[U2]);     // Green Light
  shiftOut(dataPin, clockPin, dataArrayToFGC[U3]);       // Red Light

  // return the latch pin high to signal chip that it
  // no longer needs to listen for information
  digitalWrite(latchPin, HIGH);
  digitalWrite(Clear, LOW);
  delay(200); // only show to see LED data.
}

// the heart of the program
void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
  // This shifts 8 bits out MSB first,
  // on the rising edge of the clock,
  // clock idles low
  // internal function setup
  int i = 0;
  int pinState;
  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, OUTPUT);
  // clear everything out just in case to
  // prepare shift register for bit shifting
  digitalWrite(myDataPin, LOW);
  digitalWrite(myClockPin, LOW);
  // for each bit in the byte myDataOut�
  // NOTICE THAT WE ARE COUNTING DOWN in our for loop
  // This means that %00000001 or "1" will go through such
  // that it will be pin Q0 that lights.
  for (i = 7; i >= 0; i--)  {
    digitalWrite(myClockPin, LOW);
    // if the value passed to myDataOut and a bitmask result
    // true then... so if we are at i=6 and our value is
    // %11010100 it would the code compares it to %01000000
    // and proceeds to set pinState to 1.
    if ( myDataOut & (1 << i) ) {
      pinState = 1;
    }
    else {
      pinState = 0;
    }
    // Sets the pin to HIGH or LOW depending on pinState
    digitalWrite(myDataPin, pinState);
    // register shifts bits on upstroke of clock pin
    digitalWrite(myClockPin, HIGH);
    // zero the data pin after shift to prevent bleed through
    digitalWrite(myDataPin, LOW);
  }
  // stop shifting
  digitalWrite(myClockPin, LOW);
}


uint8_t switchesValue(uint8_t switchesRow) {

  uint8_t data = 0;
  for (uint8_t switchIndex = 0; switchIndex < sizeof(U_SW[switchesRow]) / sizeof(*U_SW[switchesRow]); switchIndex++) { // Whatever FGC stands for...
    data = (data << 1) + digitalRead(U_SW[switchesRow][switchIndex]);
  }

  return data;

}
74HC595
74HC595
74HC595