Arduino + Shift Register Help needed

Hello I got an old circuit card I need to create an small code for to confirme its still is working.
It has 3 Parallel output and 6 parallel load shift registers connected in serial together.
I need to write to the 3 first parallel shift registers then read from the next 6 shift registers.
Is there an easy way using an arduino to do this?
I found a way to read, but not read and write at the same time.

Ref. image added that shows how its connected together.

What have you found. Technically speaking, you do not do both at the same time.
You write to the first 3 registers until the final pin of the 3rd is triggered and then you read from the registers 1 by one. Does what you read depend on what you have written, or could you read first and write after ?

Maybe you should separate the trigger for the 74HC165 from the QH of the 74HC164 and use a separate pin for that.

Ye looks like write first, then read.

On spliting it up is not possible this is how the circuit card is designed. It cant be changed.
Its and 15-20 year old card.

Read.

const byte latchPin = 9;        // to latch the inputs into the registers
const byte clockPin = 13;       // I choose the SCK pin
const byte dataPin = 12;        // I choose the MISO pin
uint32_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;
  for( int i=24; i>=0; i-=8)
  {
    optionSwitch |= ((uint32_t) ReadOne165()) << i;
  }

  for( int i = 0; i<32; i++)
  {
    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);
}

Link: Use Shift Register 74HC165 With Arduino

Needed to edit the Image.
One wire for Serial start on 165 was wrong

So how are you reading anything, i mean i guess your first set of reads is mute, then you read 3 registers twice. and then start over.

From the datasheet of the 74HC164 and the datasheet for the 74hc165 They are both outputs ! so what is it you are connecting to those outputs that you are reading ?

I used the last 4 74HC165 to test the code.

const byte latchPin = 9;        // to latch the inputs into the registers
const byte clockPin = 13;       // I choose the SCK pin
const byte dataPin = 12;        // I choose the MISO pin
uint32_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;
  for( int i=24; i>=0; i-=8)
  {
    optionSwitch |= ((uint32_t) ReadOne165()) << i;
  }

  for( int i = 0; i<32; i++)
  {
    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   ↑");
      Serial.println(optionSwitch, BIN);
    }
  }
 
  oldOptionSwitch = optionSwitch;
  delay(250);      // 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);
}

That works fine.
Only thing to do now is to find out how to add the rest.
I found out the last 4 ICs are on a seperat card. so can test by itself. but not the mix of 165 and 164 on the first card.

Test Program Online

They basically work the same way, just the 164 has an extra Input A that should be pulled HIGH if the B input works as normal.

ok tested the code show above.
For reading 4 74HC165 shift registers its fine. But not able to change the code to read 6 74HX165 ships

Changing my arduino to Arduino DUE, but how can I change the code from 32 bit data to 48 bit data?

The data to 164 will for now be LOW. so data is not needed.

Don't know what the change to the Due has to do with it, but i guess it would be as simple as storing the data in a 6 field 8-bit array for starters.

uint8_t oldOptionSwitch[6] = {0, 0, 0, 0, 0, 0};   // previous state of all the inputs

and

 uint8_t optionSwitch[6] ;
  for( int i = 6; i < 6; i++)
  {
    optionSwitch[i] = ReadOne165();
  }

  for( int i = 0; i<48; i++)
  {
    uint8_t ndx = i / 8; // creates indices 0 - 5
    uint8_t bit = i % 8; // modulo indcates bits 0 - 7
    if( bitRead( optionSwitch[indx], bit) != bitRead( oldOptionSwitch[ndx], bit))
    {
      Serial.print( "Switch ");
      if( i < 10)
        Serial.print( " ");
      Serial.print( i);
      Serial.print( " is now ");
      Serial.println( bitRead( optionSwitch[ndx], bit) == 0 ? "down ↓" : "up   ↑");
      Serial.println(optionSwitch[ndx], BIN);  // shows just the byte the button is in i suspect just for debug 
    }
  }
 for (uint8_t i = 0; i < 6; i++) {
   oldOptionSwitch[i] = optionSwitch[i];
 }

or i guess you could use a uint64_t with the previous code if it is supported in the platform your are using.

got it working. I forgot to change the "uint32_t oldOptionSwitch = 0;" to unit64_t on top of the code.

Only missing the 164 code now

The HC164 should work flawlessly. Here is a version on Wokwi that uses unions to convert 32-bit and 8-bit seamlessly and hardware SPI.

As the HC164 isn't able to latch the data (as opposed to the HC595), any transmission is "visible"