// File : 74HC165-16bit.ino
// // AUTHOR: Hakan GOKMEN
// Cascade of four 74HC165 shift-in registers.
// Only three pins are used on the Arduino board, to read 16 switches.
//
// Using the 74HC165 is safe, because a pulse to the Latch pin 
// ('PL' on the 74HC165) will make a new start every time. 
// In case of an error or a wrong clock pulse by noise, 
// it synchronizes the data when inputs are read the next time.
//
// Based on:
//    74HC165 Shift register input example
//   (1) https://wokwi.com/projects/306024460940476993


const byte latchPin = 8;       // PL(Paralel Load)/latch the inputs into the registers
const byte clockPin = 9;       // The SCK pin
const byte dataPin = 10;       // Data pin out like  MISO pin

//uint32_t oldOptionSwitch = 0;   // 32 bit için aktif et
uint16_t oldOptionSwitch = 0;     // previous state of all the inputs

const int pulseWidth = 10;      // pulse width in microseconds

void setup ()
{
  Serial.begin( 115200);
  Serial.println( "Turn on and off the switches");
  Serial.println( "Top row is switch 0 (right) to switch 7 (left)");
  Serial.println( "Second row is 8 to 15, and so on");

  pinMode( clockPin, OUTPUT);   // clock signal, idle LOW
  pinMode( latchPin, OUTPUT);   // latch (copy input into registers), idle HIGH
  digitalWrite( latchPin, HIGH);
}

void loop ()
{
  // Give a pulse to the parallel load latch of all 74HC165
  digitalWrite( latchPin, LOW);    
  delayMicroseconds( pulseWidth);
  digitalWrite( latchPin, HIGH);

  // Reading one 74HC165 at a time and combining them into a 32 bit variable
  // The last 74HC165 is at the bottom, but the switches start numbering
  // at the top. So the first byte has to be shifted into the highest place.
  
  //uint32_t optionSwitch = 0; //32bit için aktif et.
  uint16_t optionSwitch = 0;
  for( int i=8; i>=0; i-=8) //32 bit için 24 den başlar
  {
    optionSwitch |= ((uint16_t) ReadOne165()) << i; //  //uint32_t 32 bit için
  }

  for( int i = 0; i<16; i++) //    //32 bit için 16 yı 32 yap,32 buton okunur
  {
    if( bitRead( optionSwitch, i) != bitRead( oldOptionSwitch,i))
    {
      Serial.print( "Switch ");
      if( i < 10)
        Serial.print( " ");
      Serial.print( i);
      Serial.print( " is now ");
      Serial.println( bitRead( optionSwitch, i) == 0 ? "down ↓" : "up   ↑");
    }
  }
  
  oldOptionSwitch = optionSwitch;
  delay( 25);      // slow down the sketch to avoid switch bounce
}

// The ReadOne165() function reads only 8 bits,
// because of the similar functions shiftIn() and SPI.transfer() 
// which both use 8 bits.
//
// The shiftIn() can not be used here, because the clock is set idle low
// and the shiftIn() makes the clock high to read a bit.
// The 74HC165 require to read the bit first and then give a clock pulse.
//
byte ReadOne165()
{
  byte ret = 0x00;

  // The first one that is read is the highest bit (input D7 of the 74HC165).
  for( int i=7; i>=0; i--)
  {
    if( digitalRead( dataPin) == HIGH)
      bitSet( ret, i);

    digitalWrite( clockPin, HIGH);
    delayMicroseconds( pulseWidth);
    digitalWrite( clockPin, LOW);
  }

  return( ret);
}
74HC165
74HC165