int q_pins[] = {21, 19, 18, 5 , 17 , 16 , 4, 2};

#define CS     26 // Enable pin
#define R_W    27 // Read/Write 
#define DS     25 // Serial Data
#define STCP   33 // Serial Clock
#define SHCP   32 // Storage Latch

void set_address(uint16_t address) {
  // Set the address to be accessed, into
  // the shift register
  uint8_t low = address & 0xff;
  uint8_t high = (address >> 8);
  digitalWrite(SHCP, LOW);
  shiftOut(DS, STCP, MSBFIRST, high);
  shiftOut(DS, STCP, MSBFIRST, low);
  digitalWrite(SHCP, HIGH);
}

int8_t get_memory(uint16_t address) {
  set_address(address);

  // Set the data lines to input
  for (int i = 0; i < 8; i++) {
    pinMode(q_pins[i], INPUT);
  }

  digitalWrite(R_W, LOW); // Set to read
  digitalWrite(CS, LOW); // Turn on chip select
  uint8_t byte = 0;
  for (int i = 0; i < 8; i++) {
    uint8_t bit = digitalRead(q_pins[i]);
    if (bit == HIGH) {
      byte = (byte >> 1) | 0x80;
    }
    else {
      byte = byte >> 1;
    }
  }
  digitalWrite(CS, HIGH);

  // Return the byte
  return byte;
}

void set_memory(uint16_t address, uint8_t byte) {
  set_address(address);

  // Set the chip enable to low, and read
  // the data lines, and then set the chip
  // enable high again

  for (int i = 0; i < 8; i++) {
    pinMode(q_pins[i], OUTPUT);
  }

  for (int i = 0; i < 8; i++) {
    digitalWrite(q_pins[i], byte & 0x01?HIGH:LOW);
    byte = byte >> 1;
  }

  // Output enable must be off
  digitalWrite(R_W, HIGH);

  // Turn on the chip select and write enable
//  digitalWrite(WE, LOW); // Turn on write enable
  digitalWrite(CS, LOW);
  // Turn them off again
  digitalWrite(CS, HIGH);
  digitalWrite(R_W, HIGH); 
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  pinMode(DS, OUTPUT);     // Serial data pin
  pinMode(CS, OUTPUT); // Chip enable pin
  pinMode(R_W, OUTPUT); // Output enable pin
  pinMode(STCP, OUTPUT);   // Shift register clock
  pinMode(SHCP, OUTPUT);   // Shift register output latch

  // Set enable to high, so no chip is selected
  digitalWrite(CS, HIGH);

  // Set the data lines to input
  for (int i = 0; i < 8; i++) {
    pinMode(q_pins[i], INPUT);
  }

  uint8_t byte = 0;

  char *data_first = "This is some data that will be stored in the first memory chip.";
  char *data_second = "This is some data that will be stored in the second memory chip";

  int i = 0;
  for (i = 0; i < strlen(data_first); i++) {
    set_memory(i, data_first[i]);
  }
  set_memory(i, 0);
  
  // Dump string from the first memory chip
  unsigned long pos = 0;
  while ((byte = get_memory(pos)) != 0) {
    Serial.print((char)byte);
    pos++;
  }
  Serial.println("");

  for (i = 0; i < strlen(data_second); i++) {
    set_memory(i + 2048, data_second[i]);
  }
  set_memory(i + 2048,0);

  // Dump string from the second memory chip
  pos = 2048;
  while ((byte = get_memory(pos)) != 0) {
    Serial.print((char)byte);
    pos++;
  }
  Serial.println("");

  // Read the first 32 bytes from the first chip
  Serial.println("Dump data of 64 bytes from the first memory chip.");
  for (i = 0; i < 64; i++) {
    byte = get_memory(i);
    Serial.print("Memory: ");
    Serial.print(i);
    Serial.print(" - Byte: ");
    Serial.println(byte);
  }

  // Read the first 32 bytes from the second chip
  Serial.println("Dump data of 64 bytes from the second memory chip.");
  for (i = 0; i < 64; i++) {
    byte = get_memory(i+2048);
    Serial.print("Memory: ");
    Serial.print(i+2048);
    Serial.print(" - Byte: ");
    Serial.println(byte);
  }

  set_memory(0, 255);
  byte = get_memory(0);
  Serial.println(byte);

}

void loop() {
  // put your main code here, to run repeatedly:
  delay(10); // this speeds up the simulation
}
74HC595
6116 2K RAMBreakout
6116 2K RAMBreakout
74HC595